浏览代码

Merge branch 'compdfkit_demo_win_dev_measure' into compdfkit_demo_win_dev

# Conflicts:
#	Demo/Examples/Compdfkit_Tools/Compdfkit_Tools.csproj
#	Demo/Examples/Compdfkit_Tools/Form/Property/ComboBoxProperty.xaml.cs
#	Demo/Examples/Compdfkit_Tools/Properties/AssemblyInfo.cs
#	Demo/Examples/DigitalSignature/DigitalSignature.csproj
#	Demo/Examples/Examlpes.sln
#	Demo/Examples/Forms/Forms.csproj
#	Demo/Examples/Samples/DigitalSignatureTest/CS/DigitalSignatureTest.csproj
#	Demo/Examples/packages/ComPDFKit.NetFramework.1.11.0/build/x64/ComPDFKit.dll
#	Demo/Examples/packages/ComPDFKit.NetFramework.1.11.0/build/x86/ComPDFKit.dll
zhuyi 10 月之前
父节点
当前提交
fa16340180
共有 42 个文件被更改,包括 5326 次插入28 次删除
  1. 26 0
      Demo/Examples/Compdfkit_Tools/Annotation/PDFAnnotationList/PDFAnnotationListUI/CPDFAnnoationListUI.xaml
  2. 1 1
      Demo/Examples/Compdfkit_Tools/Annotation/PDFAnnotationPanel/PDFAnnotationUI/CPDFStampUI.xaml.cs
  3. 21 0
      Demo/Examples/Compdfkit_Tools/Common/BarControl/CPDFMeasureBarControl.xaml
  4. 354 0
      Demo/Examples/Compdfkit_Tools/Common/BarControl/CPDFMeasureBarControl.xaml.cs
  5. 73 6
      Demo/Examples/Compdfkit_Tools/Compdfkit_Tools.csproj
  6. 72 0
      Demo/Examples/Compdfkit_Tools/Measure/MeasureControl.xaml
  7. 525 0
      Demo/Examples/Compdfkit_Tools/Measure/MeasureControl.xaml.cs
  8. 126 0
      Demo/Examples/Compdfkit_Tools/Measure/MeasureInfoPanel.xaml
  9. 185 0
      Demo/Examples/Compdfkit_Tools/Measure/MeasureInfoPanel.xaml.cs
  10. 13 0
      Demo/Examples/Compdfkit_Tools/Measure/MeasurePropertyControl.xaml
  11. 100 0
      Demo/Examples/Compdfkit_Tools/Measure/MeasurePropertyControl.xaml.cs
  12. 100 0
      Demo/Examples/Compdfkit_Tools/Measure/MeasureSettingDialog.xaml
  13. 282 0
      Demo/Examples/Compdfkit_Tools/Measure/MeasureSettingDialog.xaml.cs
  14. 97 0
      Demo/Examples/Compdfkit_Tools/Measure/MeasureSettingPanel.xaml
  15. 474 0
      Demo/Examples/Compdfkit_Tools/Measure/MeasureSettingPanel.xaml.cs
  16. 70 0
      Demo/Examples/Compdfkit_Tools/Measure/Property/MultilineProperty.xaml
  17. 293 0
      Demo/Examples/Compdfkit_Tools/Measure/Property/MultilineProperty.xaml.cs
  18. 70 0
      Demo/Examples/Compdfkit_Tools/Measure/Property/PolygonalProperty.xaml
  19. 298 0
      Demo/Examples/Compdfkit_Tools/Measure/Property/PolygonalProperty.xaml.cs
  20. 87 0
      Demo/Examples/Compdfkit_Tools/Measure/Property/StraightnessProperty.xaml
  21. 308 0
      Demo/Examples/Compdfkit_Tools/Measure/Property/StraightnessProperty.xaml.cs
  22. 1 1
      Demo/Examples/Compdfkit_Tools/PDFView/PDFDisplaySettings/PDFDisplaySettingsUI/CPDFViewModeUI.xaml
  23. 0 8
      Demo/Examples/ContentEditor/ContentEditor.csproj
  24. 16 2
      Demo/Examples/Examlpes.sln
  25. 8 0
      Demo/Examples/Forms/Forms.csproj
  26. 6 0
      Demo/Examples/Measure/App.config
  27. 9 0
      Demo/Examples/Measure/App.xaml
  28. 34 0
      Demo/Examples/Measure/App.xaml.cs
  29. 二进制
      Demo/Examples/Measure/ComPDFKit_Logo.ico
  30. 314 0
      Demo/Examples/Measure/MainWindow.xaml
  31. 892 0
      Demo/Examples/Measure/MainWindow.xaml.cs
  32. 164 0
      Demo/Examples/Measure/Measure.csproj
  33. 二进制
      Demo/Examples/Measure/PDF32000_2008.pdf
  34. 55 0
      Demo/Examples/Measure/Properties/AssemblyInfo.cs
  35. 63 0
      Demo/Examples/Measure/Properties/Resources.Designer.cs
  36. 117 0
      Demo/Examples/Measure/Properties/Resources.resx
  37. 26 0
      Demo/Examples/Measure/Properties/Settings.Designer.cs
  38. 7 0
      Demo/Examples/Measure/Properties/Settings.settings
  39. 5 0
      Demo/Examples/Measure/packages.config
  40. 1 0
      Demo/Examples/PDFViewer/MainPage.xaml
  41. 25 4
      Demo/Examples/PDFViewer/MainPage.xaml.cs
  42. 8 6
      Demo/Examples/PDFViewer/PDFViewer.csproj

+ 26 - 0
Demo/Examples/Compdfkit_Tools/Annotation/PDFAnnotationList/PDFAnnotationListUI/CPDFAnnoationListUI.xaml

@@ -100,6 +100,32 @@
                                 <Grid x:Name="StampGrid" Visibility="{Binding BindProperty.CurrentAnnotationType, Converter={StaticResource AnnotArgsTypeToVisibilityConverter}, ConverterParameter = AnnotStamp}">
                                     <Path Data="M9.98201 7.97521C11.1875 7.28619 12 5.98798 12 4.5C12 2.29086 10.2091 0.5 8 0.5C5.79086 0.5 4 2.29086 4 4.5C4 5.98798 4.81248 7.2862 6.018 7.97522C6.10745 8.10318 6.5 8.69622 6.5 9.25C6.5 9.875 6 10.5 6 10.5H0V12H16V10.5H10C10 10.5 9.5 9.875 9.5 9.25C9.5 8.69621 9.89256 8.10316 9.98201 7.97521ZM16 15.5V14H0V15.5H16Z" Fill="#43474D"></Path>
                                 </Grid>
+                                <Grid x:Name="LineMeasureGrid" Visibility="{Binding BindProperty.CurrentAnnotationType, Converter={StaticResource AnnotArgsTypeToVisibilityConverter}, ConverterParameter = LineMeasure}">
+                                    <Path Fill="#43474D">
+                                        <Path.Data>
+                                            M17.7782 5.75646L14.2427 2.22093L13.0052 3.45837L15.4802 5.93333L14.4195 6.99399L11.9446 4.51903L10.1768
+                                            6.28679L12.6518 8.76175L11.5911 9.82241L9.11615 7.34745L7.34838 9.11522L9.82334 11.5902L8.76268
+                                            12.6508L6.28772 10.1759L4.51996 11.9436L6.99492 14.4186L5.93426 15.4793L3.4593 13.0043L2.22186
+                                            14.2417L5.75739 17.7773L17.7782 5.75646ZM15.3033 1.16027L14.2427 0.0996094L13.182 1.16027L1.1612
+                                            13.1811L0.100539 14.2417L1.1612 15.3024L4.69673 18.8379L5.75739 19.8986L6.81805 18.8379L18.8389 
+                                            6.81712L19.8995 5.75646L18.8389 4.6958L15.3033 1.16027Z
+                                        </Path.Data>
+                                    </Path>
+                                </Grid>
+                                <Grid x:Name="PolyLineMeasureGrid" Visibility="{Binding BindProperty.CurrentAnnotationType, Converter={StaticResource AnnotArgsTypeToVisibilityConverter}, ConverterParameter = PolyLineMeasure}">
+                                    <Path Fill="#43474D">
+                                        <Path.Data>
+                                            M0.5 3C0.5 1.89543 1.39543 1 2.5 1C3.33934 1 4.05793 1.51704 4.35462 2.25H15.6454C15.9421 1.51704 16.6607 1 
+                                            17.5 1C18.6046 1 19.5 1.89543 19.5 3C19.5 3.83934 18.983 4.55793 18.25 4.85462V17V17.75H17.5H13.7011L14.5167
+                                            18.5765L13.5138 19.5928L11.4986 17.5505L10.9972 17.0423L11.4986 16.5342L13.5138 14.4918L14.5167 15.5082L13.7847
+                                            16.25H16.75V4.85462C16.2487 4.65168 15.8483 4.25135 15.6454 3.75H4.35462C4.15168 4.25135 3.75135 4.65168 3.25
+                                            4.85462V16.25H6.25V15H7.75V19H6.25V17.75H2.5H1.75V17V4.85462C1.01704 4.55793 0.5 3.83934 0.5 3Z
+                                        </Path.Data>
+                                    </Path>
+                                </Grid>
+                                <Grid x:Name="PolygonMeasureGrid" Visibility="{Binding BindProperty.CurrentAnnotationType, Converter={StaticResource AnnotArgsTypeToVisibilityConverter}, ConverterParameter = PolygonMeasure}">
+                                    <Path Data="M1.37111 7.6963L10 1.42705L18.6289 7.6963L15.3329 17.8402H4.66705L1.37111 7.6963Z" Stroke="#43474D"></Path>
+                                </Grid>
                             </Canvas>
                             <TextBlock Text="{Binding BindProperty.CreateDate}" Grid.Column="1" Margin="10,0,0,0"></TextBlock>
                         </Grid>

+ 1 - 1
Demo/Examples/Compdfkit_Tools/Annotation/PDFAnnotationPanel/PDFAnnotationUI/CPDFStampUI.xaml.cs

@@ -75,7 +75,7 @@ namespace Compdfkit_Tools.Annotation.PDFAnnotationPanel.PDFAnnotationUI
         private void CPDFOpacityControl_OpacityChanged(object sender, EventArgs e)
         {
             PropertyChanged?.Invoke(this, new CPDFStampData());
-        }
+        } 
 
         private void Text_Click(object sender, RoutedEventArgs e)
         {

+ 21 - 0
Demo/Examples/Compdfkit_Tools/Common/BarControl/CPDFMeasureBarControl.xaml

@@ -0,0 +1,21 @@
+<UserControl x:Class="Compdfkit_Tools.PDFControl.CPDFMeasureBarControl"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:Compdfkit_Tools.PDFControl"
+             mc:Ignorable="d" 
+             Loaded="UserControl_Loaded"
+             d:DesignHeight="450" d:DesignWidth="800">
+    <UserControl.Resources>
+        <ResourceDictionary>
+            <ResourceDictionary.MergedDictionaries>
+                <ResourceDictionary Source="../../Asset/Styles/ToggleButtonStyle.xaml"></ResourceDictionary>
+            </ResourceDictionary.MergedDictionaries>
+        </ResourceDictionary>
+    </UserControl.Resources>
+    <Border>
+        <StackPanel  Name="MeasureGrid" Orientation="Horizontal" HorizontalAlignment="Center">
+        </StackPanel>
+    </Border>
+</UserControl>

文件差异内容过多而无法显示
+ 354 - 0
Demo/Examples/Compdfkit_Tools/Common/BarControl/CPDFMeasureBarControl.xaml.cs


+ 73 - 6
Demo/Examples/Compdfkit_Tools/Compdfkit_Tools.csproj

@@ -45,12 +45,6 @@
     <ApplicationIcon>ComPDFKit_Logo.ico</ApplicationIcon>
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="ComPDFKit.Desk, Version=1.11.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\ComPDFKit.NetFramework.1.11.0\lib\ComPDFKit.Desk.dll</HintPath>
-    </Reference>
-    <Reference Include="ComPDFKit.Viewer, Version=1.11.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\ComPDFKit.NetFramework.1.11.0\lib\ComPDFKit.Viewer.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>
@@ -116,6 +110,9 @@
     <Compile Include="Common\BarControl\CPDFDigitalSignatureBarControl.xaml.cs">
       <DependentUpon>CPDFDigitalSignatureBarControl.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Common\BarControl\CPDFMeasureBarControl.xaml.cs">
+      <DependentUpon>CPDFMeasureBarControl.xaml</DependentUpon>
+    </Compile>
     <Compile Include="Common\BarControl\CPDFPageEditBarControl.xaml.cs">
       <DependentUpon>CPDFPageEditBarControl.xaml</DependentUpon>
     </Compile>
@@ -389,6 +386,30 @@
     <Compile Include="Form\Property\TextFieldProperty.xaml.cs">
       <DependentUpon>TextFieldProperty.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Measure\MeasureControl.xaml.cs">
+      <DependentUpon>MeasureControl.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Measure\MeasureInfoPanel.xaml.cs">
+      <DependentUpon>MeasureInfoPanel.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Measure\MeasurePropertyControl.xaml.cs">
+      <DependentUpon>MeasurePropertyControl.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Measure\MeasureSettingDialog.xaml.cs">
+      <DependentUpon>MeasureSettingDialog.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Measure\MeasureSettingPanel.xaml.cs">
+      <DependentUpon>MeasureSettingPanel.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Measure\Property\StraightnessProperty.xaml.cs">
+      <DependentUpon>StraightnessProperty.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Measure\Property\PolygonalProperty.xaml.cs">
+      <DependentUpon>PolygonalProperty.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Measure\Property\MultilineProperty.xaml.cs">
+      <DependentUpon>MultilineProperty.xaml</DependentUpon>
+    </Compile>
     <Compile Include="PageEdit\PageEditControl\PageEditControl.xaml.cs">
       <DependentUpon>PageEditControl.xaml</DependentUpon>
     </Compile>
@@ -767,6 +788,10 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
+    <Page Include="Common\BarControl\CPDFMeasureBarControl.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="Common\BarControl\CPDFPageEditBarControl.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
@@ -1053,6 +1078,38 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
+    <Page Include="Measure\MeasureControl.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="Measure\MeasureInfoPanel.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="Measure\MeasurePropertyControl.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="Measure\MeasureSettingDialog.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="Measure\MeasureSettingPanel.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="Measure\Property\StraightnessProperty.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="Measure\Property\PolygonalProperty.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="Measure\Property\MultilineProperty.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="PageEdit\PageEditControl\PageEditControl.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
@@ -1201,6 +1258,16 @@
   <ItemGroup>
     <Folder Include="DigitalSignature\CPDFSignatureListControl\" />
   </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\compdfkit_windows\ComPDFKit\ComPDFKitCSharp\ComPDFKit.Desk.csproj">
+      <Project>{56e518ad-c126-4b48-9a09-0a64c87020e4}</Project>
+      <Name>ComPDFKit.Desk</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\compdfkit_windows\ComPDFKit\ComPDFKitDesktop\ComPDFKit.Viewer\ComPDFKit.Viewer.csproj">
+      <Project>{18ec356d-8130-49d4-b4e6-ac290e1065b7}</Project>
+      <Name>ComPDFKit.Viewer</Name>
+    </ProjectReference>
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <Import Project="..\packages\ComPDFKit.NetFramework.1.11.0\build\ComPDFKit.NetFramework.targets" Condition="Exists('..\packages\ComPDFKit.NetFramework.1.11.0\build\ComPDFKit.NetFramework.targets')" />
   <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">

+ 72 - 0
Demo/Examples/Compdfkit_Tools/Measure/MeasureControl.xaml

@@ -0,0 +1,72 @@
+<UserControl x:Class="Compdfkit_Tools.Measure.MeasureControl"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:Compdfkit_Tools.Measure"
+             mc:Ignorable="d" 
+             xmlns:cpdftools="clr-namespace:Compdfkit_Tools.PDFControl"
+             xmlns:cpdfcommon="clr-namespace:Compdfkit_Tools.Common"    
+             Loaded="UserControl_Loaded"
+             d:DesignHeight="450" d:DesignWidth="800">
+    <UserControl.Resources>
+        <ResourceDictionary>
+            <ResourceDictionary.MergedDictionaries>
+                <ResourceDictionary Source="../Asset/Styles/ToggleButtonStyle.xaml"></ResourceDictionary>
+                <ResourceDictionary Source="../Asset/Styles/ButtonStyle.xaml"></ResourceDictionary>
+                <ResourceDictionary Source="../Asset/Styles/ComboBoxStyle.xaml"></ResourceDictionary>
+            </ResourceDictionary.MergedDictionaries>
+            <RoutedUICommand x:Key="Undo" Text="Undo"></RoutedUICommand>
+            <RoutedUICommand x:Key="Redo" Text="Redo"></RoutedUICommand>
+        </ResourceDictionary>
+    </UserControl.Resources>
+    <Grid>
+        <Grid Name="BodyGrid">
+            <Grid.RowDefinitions>
+                <RowDefinition Height="auto"/>
+                <RowDefinition Height="*"/>
+            </Grid.RowDefinitions>
+            <Grid.ColumnDefinitions>
+                <ColumnDefinition Width="0"></ColumnDefinition>
+                <ColumnDefinition Width="0"></ColumnDefinition>
+                <ColumnDefinition Width="*"></ColumnDefinition>
+                <ColumnDefinition Width="auto"></ColumnDefinition>
+            </Grid.ColumnDefinitions>
+            <Border x:Name="ToolBarContainer" Height="45" Visibility="Visible" BorderThickness="1" BorderBrush="#1A000000" Background="#F2F3F5" Grid.ColumnSpan="4">
+                <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
+                    <cpdftools:CPDFMeasureBarControl x:Name="PDFMeasureTool"  Grid.ColumnSpan="4" Height="44"/>
+                </StackPanel>
+            </Border>
+            <Border Grid.Row="1" Visibility="Collapsed" Name="BotaContainer"></Border>
+            <GridSplitter  Grid.Row="1" Name="Splitter" Grid.Column="1" Width="15" ResizeBehavior="PreviousAndNext" Visibility="Collapsed">
+                <GridSplitter.Template>
+                    <ControlTemplate TargetType="{x:Type GridSplitter}">
+                        <Border BorderThickness="{TemplateBinding Border.BorderThickness}"
+                         BorderBrush="{TemplateBinding Border.BorderBrush}"
+                         Background="{TemplateBinding Panel.Background}" >
+                            <Path Fill="Gray" VerticalAlignment="Center">
+                                <Path.Data>
+                                    M15 3.75H1V2.25H15V3.75ZM15 8.75H1V7.25H15V8.75ZM1 13.75H15V12.25H1V13.75Z
+                                </Path.Data>
+                            </Path>
+                        </Border>
+                    </ControlTemplate>
+                </GridSplitter.Template>
+            </GridSplitter>
+            <Grid Grid.Row="1" Grid.Column="2">
+                <Border x:Name="PDFGrid" Background="#CECECE"></Border>
+                <local:MeasureInfoPanel x:Name="InfoPanel" Width="300" HorizontalAlignment="Right" Margin="0,20,30,0"
+                                        Visibility="Collapsed" VerticalAlignment="Top" 
+                                        SettingClick="MeasureInfoPanel_SettingClick"></local:MeasureInfoPanel>
+                <local:MeasureSettingPanel x:Name="SettingPanel" HorizontalAlignment="Center" VerticalAlignment="Center" 
+                             Visibility="Collapsed"
+                             CancelEvent="SettingPanel_CancelEvent"
+                             DoneEvent="SettingPanel_DoneEvent">
+
+                </local:MeasureSettingPanel>
+            </Grid>
+            <Border Grid.Column="3" Name="PropertyContainer" Grid.Row="1" Visibility="Collapsed" ></Border>
+            <cpdfcommon:PageNumberControl  Grid.Column="2" Grid.Row="1" x:Name="FloatPageTool" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,20"></cpdfcommon:PageNumberControl>
+        </Grid>
+    </Grid>
+</UserControl>

+ 525 - 0
Demo/Examples/Compdfkit_Tools/Measure/MeasureControl.xaml.cs

@@ -0,0 +1,525 @@
+using ComPDFKit.Measure;
+using ComPDFKit.PDFAnnotation;
+using Compdfkit_Tools.Helper;
+using Compdfkit_Tools.PDFControl;
+using ComPDFKitViewer;
+using ComPDFKitViewer.AnnotEvent;
+using ComPDFKitViewer.PdfViewer;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+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;
+
+
+
+namespace Compdfkit_Tools.Measure
+{
+    /// <summary>
+    /// MeasureControl.xaml 的交互逻辑
+    /// </summary>
+    public partial class MeasureControl : UserControl
+    {
+        public MeasurePropertyControl measurePropertyControl = new MeasurePropertyControl();
+        private CPDFDisplaySettingsControl displaySettingsControl;
+
+        private PDFViewControl PdfViewControl = new PDFViewControl();
+
+        private PanelState panelState = PanelState.GetInstance();
+
+        public event EventHandler ExpandEvent;
+
+        public MeasureControl()
+        {
+            InitializeComponent();
+            MeasureSetting.MeasureChanged += MeasureSetting_MeasureChanged;
+        }
+
+        private void MeasureSetting_MeasureChanged(object sender, MeasureEventArgs e)
+        {
+            InfoPanel.SetMeasureType(e.Type);
+            InfoPanel.SetMeasureInfo(e);
+
+            switch (e.Type)
+            {
+                case CPDFMeasureType.CPDF_DISTANCE_MEASURE:
+                case CPDFMeasureType.CPDF_PERIMETER_MEASURE:
+                    SettingPanel.ShowAreaAndLength(Visibility.Collapsed);
+                    break;
+                case CPDFMeasureType.CPDF_AREA_MEASURE:
+                    SettingPanel.ShowAreaAndLength(Visibility.Visible);
+                    break;
+                default:
+                    break;
+            }
+
+            SettingPanel.BindMeasureSetting(e);
+        }
+        #region Init PDFViewer
+
+        public void InitWithPDFViewer(PDFViewControl pdfViewControl, CPDFViewer pdfViewer)
+        {
+            PdfViewControl = pdfViewControl;
+            PdfViewControl.PDFView = pdfViewer;
+            PDFMeasureTool.InitWithPDFViewer(pdfViewer, measurePropertyControl, this);
+            FloatPageTool.InitWithPDFViewer(pdfViewer);
+            PDFGrid.Child = PdfViewControl;
+
+            panelState.PropertyChanged -= PanelState_PropertyChanged;
+            panelState.PropertyChanged += PanelState_PropertyChanged;
+            pdfViewControl.PDFView.AnnotActiveHandler -= PDFView_AnnotActiveHandler;
+            pdfViewControl.PDFView.AnnotActiveHandler += PDFView_AnnotActiveHandler;
+            pdfViewControl.PDFView.AnnotCommandHandler -= PDFView_AnnotCommandHandler;
+            pdfViewControl.PDFView.AnnotCommandHandler += PDFView_AnnotCommandHandler;
+            SetInfoPanelVisble(false, false);
+            SettingPanel.PdfViewControl= pdfViewControl;
+        }
+
+        private void PDFView_AnnotCommandHandler(object sender, AnnotCommandArgs e)
+        {
+            switch (e.CommandType)
+            {
+                case CommandType.Context:
+                    if (e.CommandTarget == TargetType.Annot && e.PressOnAnnot)
+                    {
+                        e.Handle = true;
+                        e.PopupMenu = new ContextMenu();
+                        e.PopupMenu.Items.Add(new MenuItem() { Header = "Delete", Command = ApplicationCommands.Delete, CommandTarget = (UIElement)sender });
+                        MenuItem menuItem = new MenuItem();
+                        menuItem.Header = "Measurement Settings";
+                        menuItem.Click += (item, param) =>
+                        {
+                            SettingPanel.UpdateArgsList = e.AnnotEventArgsList;
+                            SettingPanel.BindMeasureSetting();
+                            SetInfoPanelVisble(false, true);
+                        };
+
+                        MenuItem propertyItem = new MenuItem();
+                        propertyItem.Header = "Properties";
+                        propertyItem.Click += (item, param) =>
+                        {
+                            ExpandEvent?.Invoke(this, new EventArgs());
+                        };
+                        e.PopupMenu.Items.Add(menuItem);
+                        e.PopupMenu.Items.Add(propertyItem);
+                    }
+                    break;
+
+                case CommandType.Delete:
+                    e.DoCommand();
+                    break;
+                default:
+                    break;
+            }
+        }
+
+
+
+        private void PDFView_AnnotActiveHandler(object sender, AnnotAttribEvent e)
+        {
+            if (e == null || e.IsAnnotCreateReset)
+            {
+                if (e == null)
+                {
+                    measurePropertyControl?.ClearMeasurePanel();
+                    if(PDFMeasureTool.ToolChecked()==false)
+                    {
+                        SetInfoPanelVisble(false, false);
+                    }
+                }
+                return;
+            }
+            else
+            {
+                switch (e.GetAnnotTypes())
+                {
+                    case AnnotArgsType.LineMeasure:
+                        LineMeasureArgs LineArgs = e.GetAnnotHandlerEventArgs(AnnotArgsType.LineMeasure).First() as LineMeasureArgs;
+                        panelState.RightPanel = PanelState.RightPanelState.PropertyPanel;
+                        measurePropertyControl.SetPropertyForMeasureCreate(LineArgs, e);
+                        SetInfoPanelVisble(true, false);
+                        SetMeasureInfoPanel(LineArgs.GetPDFAnnot(), LineArgs);
+                        break;
+                    case AnnotArgsType.PolygonMeasure:
+                        PolygonMeasureArgs polygonArgs = e.GetAnnotHandlerEventArgs(AnnotArgsType.PolygonMeasure).First() as PolygonMeasureArgs;
+                        panelState.RightPanel = PanelState.RightPanelState.PropertyPanel;
+                        measurePropertyControl.SetPropertyForMeasureCreate(polygonArgs, e);
+                        SetInfoPanelVisble(true, false);
+                        SetMeasureInfoPanel(polygonArgs.GetPDFAnnot(),polygonArgs);
+                        break;
+
+                    case AnnotArgsType.PolyLineMeasure:
+                        PolyLineMeasureArgs polyLineArgs = e.GetAnnotHandlerEventArgs(AnnotArgsType.PolyLineMeasure).First() as PolyLineMeasureArgs;
+                        panelState.RightPanel = PanelState.RightPanelState.PropertyPanel;
+                        measurePropertyControl.SetPropertyForMeasureCreate(polyLineArgs, e);
+                        SetInfoPanelVisble(true, false);
+                        SetMeasureInfoPanel(polyLineArgs.GetPDFAnnot(),polyLineArgs);
+                        break;
+                }
+            }
+        }
+
+        private void SetMeasureInfoPanel(CPDFAnnotation rawAnnot,AnnotHandlerEventArgs annotArgs=null)
+        {
+            if (rawAnnot == null)
+            {
+                return;
+            }
+            try
+            {
+                if (rawAnnot.Type == C_ANNOTATION_TYPE.C_ANNOTATION_LINE)
+                {
+                    CPDFLineAnnotation lineAnnot = rawAnnot as CPDFLineAnnotation;
+                    if (lineAnnot.IsMersured() && lineAnnot.Points != null && lineAnnot.Points.Count() == 2)
+                    {
+                        CPDFDistanceMeasure lineMeasure = lineAnnot.GetDistanceMeasure();
+                        CPDFMeasureInfo measureInfo = lineMeasure.MeasureInfo;
+                        Vector standVector = new Vector(1, 0);
+                        Point startPoint = new Point(lineAnnot.Points[0].x, lineAnnot.Points[0].y);
+                        Point endPoint = new Point(lineAnnot.Points[1].x, lineAnnot.Points[1].y);
+                        Vector movevector = endPoint - startPoint;
+
+                        double showLenght=lineMeasure.GetMeasurementResults(CPDFCaptionType.CPDF_CAPTION_LENGTH);
+                        MeasureEventArgs measureEvent = new MeasureEventArgs();
+                        measureEvent.Angle = (int)Math.Abs(Vector.AngleBetween(movevector, standVector));
+                        measureEvent.RulerTranslateUnit = measureInfo.RulerTranslateUnit;
+                        measureEvent.RulerTranslate = measureInfo.RulerTranslate;
+                        measureEvent.RulerBase = measureInfo.RulerBase;
+                        measureEvent.RulerBaseUnit = measureInfo.RulerBaseUnit;
+                        measureEvent.MousePos = new Point(
+                           (int)Math.Abs(movevector.X),
+                           (int)Math.Abs(movevector.Y));
+                        measureEvent.Type = CPDFMeasureType.CPDF_DISTANCE_MEASURE;
+                        NumberFormatInfo formatInfo = new NumberFormatInfo();
+                        formatInfo.NumberDecimalDigits = Math.Abs(measureInfo.Precision).ToString().Length - 1;
+                        measureEvent.Distance = showLenght.ToString("N", formatInfo) + " " + measureInfo.RulerTranslateUnit;
+                        measureEvent.Precision = GetMeasureShowPrecision(measureInfo.Precision);
+
+                        MeasureSetting.InvokeMeasureChangeEvent(this, measureEvent);
+                        if(annotArgs!=null)
+                        {
+                            SettingPanel.UpdateArgsList =new List<AnnotHandlerEventArgs> { annotArgs};
+                        }
+                    }
+                }
+
+                if (rawAnnot.Type == C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE)
+                {
+                    CPDFPolylineAnnotation polylineAnnot = rawAnnot as CPDFPolylineAnnotation;
+                    if (polylineAnnot.IsMersured() && polylineAnnot.Points != null && polylineAnnot.Points.Count() >= 2)
+                    {
+                        double totalInch = 0;
+                        for (int i = 0; i < polylineAnnot.Points.Count - 1; i++)
+                        {
+                            Point endLinePoint = new Point(
+                                polylineAnnot.Points[i + 1].x,
+                                polylineAnnot.Points[i + 1].y
+                                );
+                            Point startLinePoint = new Point(
+                                polylineAnnot.Points[i].x,
+                                polylineAnnot.Points[i].y
+                                );
+                            Vector subVector = endLinePoint - startLinePoint;
+                            totalInch += subVector.Length;
+                        }
+                        totalInch = totalInch / 72D;
+                        CPDFPerimeterMeasure lineMeasure = polylineAnnot.GetPerimeterMeasure();
+                        CPDFMeasureInfo measureInfo = lineMeasure.MeasureInfo;
+                        double showLenght = lineMeasure.GetMeasurementResults(CPDFCaptionType.CPDF_CAPTION_LENGTH);
+
+                        MeasureEventArgs measureEvent = new MeasureEventArgs();
+                        measureEvent.Angle = 0;
+                        measureEvent.RulerTranslateUnit = measureInfo.RulerTranslateUnit;
+                        measureEvent.RulerTranslate = measureInfo.RulerTranslate;
+                        measureEvent.RulerBase = measureInfo.RulerBase;
+                        measureEvent.RulerBaseUnit = measureInfo.RulerBaseUnit;
+                        measureEvent.Precision = GetMeasureShowPrecision(measureInfo.Precision);
+                        measureEvent.Type = CPDFMeasureType.CPDF_PERIMETER_MEASURE;
+                        NumberFormatInfo formatInfo = new NumberFormatInfo();
+                        formatInfo.NumberDecimalDigits = Math.Abs(measureInfo.Precision).ToString().Length - 1;
+                        measureEvent.Distance = showLenght.ToString("N", formatInfo) +" "+ measureInfo.RulerTranslateUnit;
+                        MeasureSetting.InvokeMeasureChangeEvent(this, measureEvent);
+                        if (annotArgs != null)
+                        {
+                            SettingPanel.UpdateArgsList = new List<AnnotHandlerEventArgs> { annotArgs };
+                        }
+                    }
+                }
+
+                if(rawAnnot.Type== C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON)
+                {
+                    CPDFPolygonAnnotation Annot = rawAnnot as CPDFPolygonAnnotation;
+                    CPDFAreaMeasure polygonMeasure = Annot.GetAreaMeasure();
+                    CPDFMeasureInfo measureInfo = polygonMeasure.MeasureInfo;
+                    CPDFCaptionType CaptionType = measureInfo.CaptionType;
+                    bool IsArea = false;
+                    bool IsLength = false;
+                    if ((CaptionType& CPDFCaptionType.CPDF_CAPTION_AREA)== CPDFCaptionType.CPDF_CAPTION_AREA)
+                    {
+                        IsArea = true;
+                    }
+                    if ((CaptionType & CPDFCaptionType.CPDF_CAPTION_LENGTH) == CPDFCaptionType.CPDF_CAPTION_LENGTH)
+                    {
+                        IsLength = true;
+                    }
+                    SettingPanel.ChangedCheckBoxIsChecked(IsArea, IsLength);
+
+                    double inch = polygonMeasure.GetMeasurementResults(CPDFCaptionType.CPDF_CAPTION_AREA);
+                    double currentInch = polygonMeasure.GetMeasurementResults(CPDFCaptionType.CPDF_CAPTION_LENGTH);
+
+                    MeasureEventArgs measureEvent = new MeasureEventArgs();
+                    measureEvent.RulerTranslateUnit = measureInfo.RulerTranslateUnit;
+                    measureEvent.RulerTranslate = measureInfo.RulerTranslate;
+                    measureEvent.RulerBase = measureInfo.RulerBase;
+                    measureEvent.RulerBaseUnit = measureInfo.RulerBaseUnit;
+                    measureEvent.Precision = GetMeasureShowPrecision(measureInfo.Precision);
+                    measureEvent.Type = CPDFMeasureType.CPDF_AREA_MEASURE;
+
+
+                    NumberFormatInfo formatInfo = new NumberFormatInfo();
+                    formatInfo.NumberDecimalDigits = Math.Abs(measureInfo.Precision).ToString().Length - 1;
+
+                    measureEvent.Distance = currentInch.ToString("N", formatInfo) + " " + measureInfo.RulerTranslateUnit;
+                    measureEvent.Area = inch.ToString("N", formatInfo) + " sq " + measureInfo.RulerTranslateUnit;
+
+                    MeasureSetting.InvokeMeasureChangeEvent(this, measureEvent);
+                    if (annotArgs != null)
+                    {
+                        SettingPanel.UpdateArgsList = new List<AnnotHandlerEventArgs> { annotArgs };
+                    }
+                }
+            }
+            catch (Exception e)
+            {
+
+            }
+        }
+
+        private double GetMeasureRatio(string baseUnit)
+        {
+            if (baseUnit == CPDFMeasure.CPDF_PT)
+            {
+                return 1 / 72;
+            }
+            if (baseUnit == CPDFMeasure.CPDF_IN)
+            {
+                return 1;
+            }
+            if (baseUnit == CPDFMeasure.CPDF_MM)
+            {
+                return 1 / 25.4;
+            }
+            if (baseUnit == CPDFMeasure.CPDF_CM)
+            {
+                return 1 / 2.54;
+            }
+            if (baseUnit == CPDFMeasure.CPDF_M)
+            {
+                return 1 / 0.0254;
+            }
+            if (baseUnit == CPDFMeasure.CPDFO_KM)
+            {
+                return 1 / 0.0254 / 1000;
+            }
+
+            if (baseUnit == CPDFMeasure.CPDF_FT)
+            {
+                return 12;
+            }
+            if (baseUnit == CPDFMeasure.CPDF_YD)
+            {
+                return 36;
+            }
+            if (baseUnit == CPDFMeasure.CPDF_MI)
+            {
+                return 63360;
+            }
+            return 0;
+        }
+
+        private double GetMeasureShowPrecision(int precision)
+        {
+            if (precision == CPDFMeasure.PRECISION_VALUE_ZERO)
+            {
+                return 1;
+            }
+            if (CPDFMeasure.PRECISION_VALUE_ONE == precision)
+            {
+                return 0.1;
+            }
+            if (CPDFMeasure.PRECISION_VALUE_TWO == precision)
+            {
+                return 0.01;
+            }
+            if (CPDFMeasure.PRECISION_VALUE_THREE == precision)
+            {
+                return 0.001;
+            }
+            if (CPDFMeasure.PRECISION_VALUE_FOUR == precision)
+            {
+                return 0.0001;
+            }
+            return 0;
+        }
+
+        public void SetSettingsControl(CPDFDisplaySettingsControl cPDFDisplaySettingsControl)
+        {
+            displaySettingsControl = cPDFDisplaySettingsControl;
+        }
+
+        public void ClearAllToolState()
+        {
+            PDFMeasureTool.ClearAllToolState();
+        }
+        public void ClearViewerControl()
+        {
+            PDFGrid.Child = null;
+            BotaContainer.Child = null;
+            PropertyContainer.Child = null;
+            displaySettingsControl = null;
+        }
+
+        private void PanelState_PropertyChanged(object sender, PropertyChangedEventArgs e)
+        {
+            if (e.PropertyName == nameof(PanelState.IsLeftPanelExpand))
+            {
+                ExpandLeftPanel(panelState.IsLeftPanelExpand);
+            }
+            else if (e.PropertyName == nameof(PanelState.RightPanel))
+            {
+                if (panelState.RightPanel == PanelState.RightPanelState.PropertyPanel)
+                {
+                    ExpandRightPropertyPanel(measurePropertyControl, Visibility.Visible);
+                }
+                else if (panelState.RightPanel == PanelState.RightPanelState.ViewSettings)
+                {
+                    ExpandRightPropertyPanel(displaySettingsControl, Visibility.Visible);
+                }
+                else
+                {
+                    ExpandRightPropertyPanel(null, Visibility.Collapsed);
+                }
+            }
+        }
+
+        #endregion
+
+        #region Expand and collapse Panel
+
+        public void ExpandRightPropertyPanel(Visibility visible)
+        {
+            ExpandRightPropertyPanel(measurePropertyControl, visible);
+        }
+
+        public void ExpandNullRightPropertyPanel(Visibility visible)
+        {
+            ExpandRightPropertyPanel(null, visible);
+        }
+
+        public void ExpandViewSettings(Visibility visible)
+        {
+            SetViewSettings(displaySettingsControl, visible);
+        }
+
+        private void ExpandRightPropertyPanel(UIElement propertytPanel, Visibility visible)
+        {
+            PropertyContainer.Width = 260;
+            PropertyContainer.Child = propertytPanel;
+            PropertyContainer.Visibility = visible;
+        }
+
+        private void SetViewSettings(CPDFDisplaySettingsControl displaySettingsControl, Visibility visibility)
+        {
+            PropertyContainer.Child = displaySettingsControl;
+            PropertyContainer.Visibility = visibility;
+        }
+
+        public void ExpandLeftPanel(bool isExpand)
+        {
+            BotaContainer.Visibility = isExpand ? Visibility.Visible : Visibility.Collapsed;
+            Splitter.Visibility = isExpand ? Visibility.Visible : Visibility.Collapsed;
+            if (isExpand)
+            {
+                BodyGrid.ColumnDefinitions[0].Width = new GridLength(320);
+                BodyGrid.ColumnDefinitions[1].Width = new GridLength(15);
+            }
+            else
+            {
+                BodyGrid.ColumnDefinitions[0].Width = new GridLength(0);
+                BodyGrid.ColumnDefinitions[1].Width = new GridLength(0);
+            }
+        }
+
+        #endregion
+
+        private void UserControl_Loaded(object sender, RoutedEventArgs e)
+        {
+
+        }
+
+        private void MeasureInfoPanel_SettingClick(object sender, EventArgs e)
+        {
+            if (sender is MeasureInfoPanel)
+            {
+                switch ((sender as MeasureInfoPanel).MeasureType)
+                {
+                    case CPDFMeasureType.CPDF_DISTANCE_MEASURE:
+                    case CPDFMeasureType.CPDF_PERIMETER_MEASURE:
+                        SettingPanel.ShowAreaAndLength(Visibility.Collapsed);
+                        break;
+                    case CPDFMeasureType.CPDF_AREA_MEASURE:
+                        SettingPanel.ShowAreaAndLength(Visibility.Visible);
+                        break;
+                    default:
+                        break;
+                }
+            }
+            SettingPanel.ReturnToInfoPanel = true;
+            SetInfoPanelVisble(false, true);
+            SettingPanel.BindMeasureSetting();
+        }
+
+        private void SettingPanel_CancelEvent(object sender, EventArgs e)
+        {
+            SetInfoPanelVisble(SettingPanel.ReturnToInfoPanel, false);
+        }
+
+        private void SettingPanel_DoneEvent(object sender, EventArgs e)
+        {
+            SetInfoPanelVisble(SettingPanel.ReturnToInfoPanel, false);
+        }
+
+        public void SetInfoPanelVisble(bool measureInfo, bool measureSetting)
+        {
+            if (measureInfo)
+            {
+                InfoPanel.ClearMeasureInfo();
+            }
+            InfoPanel.Visibility = measureInfo ? Visibility.Visible : Visibility.Collapsed;
+            SettingPanel.Visibility = measureSetting ? Visibility.Visible : Visibility.Collapsed;
+
+        }
+
+        public void SetMeasureInfoType(CPDFMeasureType measureType)
+        {
+            InfoPanel?.SetMeasureType(measureType);
+        }
+
+        public void SetMeasureScale(CPDFMeasureType measureType, string scale)
+        {
+            InfoPanel?.SetMeasureScale(measureType,scale);
+        }
+    }
+}
+

+ 126 - 0
Demo/Examples/Compdfkit_Tools/Measure/MeasureInfoPanel.xaml

@@ -0,0 +1,126 @@
+<UserControl x:Class="Compdfkit_Tools.Measure.MeasureInfoPanel"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:Compdfkit_Tools.Measure"
+             mc:Ignorable="d" 
+             d:DesignHeight="350" d:DesignWidth="150">
+    <Border BorderBrush="LightGray" CornerRadius="4" Background="White">
+        <Border.Effect>
+            <DropShadowEffect BlurRadius="20" ShadowDepth="0" Color="Black" Opacity="0.4"/>
+        </Border.Effect>
+        <Grid Margin="20,20,0,0" Width="300" >
+            <Grid.ColumnDefinitions>
+                <ColumnDefinition Width="auto"></ColumnDefinition>
+                <ColumnDefinition Width="*"></ColumnDefinition>
+            </Grid.ColumnDefinitions>
+            <Grid.RowDefinitions>
+                <RowDefinition Height="auto"></RowDefinition>
+                <RowDefinition Height="auto"></RowDefinition>
+                <RowDefinition Height="auto"></RowDefinition>
+            </Grid.RowDefinitions>
+
+            <Path Name="MeasureIcon" Width="20" Height="20" Fill="#43474D" >
+                <Path.Data>
+                    M17.7782 5.75646L14.2427 2.22093L13.0052 3.45837L15.4802 5.93333L14.4195 6.99399L11.9446 4.51903L10.1768 
+6.28679L12.6518 8.76175L11.5911 9.82241L9.11615 7.34745L7.34838 9.11522L9.82334 11.5902L8.76268 12.6508L6.28772 
+10.1759L4.51996 11.9436L6.99492 14.4186L5.93426 15.4793L3.4593 13.0043L2.22186 14.2417L5.75739 17.7773L17.7782 
+5.75646ZM15.3033 1.16027L14.2427 0.0996094L13.182 1.16027L1.1612 13.1811L0.100539 14.2417L1.1612 15.3024L4.69673 
+18.8379L5.75739 19.8986L6.81805 18.8379L18.8389 6.81712L19.8995 5.75646L18.8389 4.6958L15.3033 1.16027Z
+                </Path.Data>
+            </Path>
+
+            <TextBlock Name="MeasureTitelText" Grid.Column="1" Margin="10,0,0,0" VerticalAlignment="Center"
+          FontSize="16">Distance Measurement</TextBlock>
+
+            <Grid Name="LinePanel" Grid.Row="1" Grid.Column="1" Margin="0,10,0,0" Visibility="Collapsed">
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition Width="80"></ColumnDefinition>
+                    <ColumnDefinition Width="auto"></ColumnDefinition>
+                </Grid.ColumnDefinitions>
+                <Grid.RowDefinitions>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                </Grid.RowDefinitions>
+                <TextBlock FontSize="14">Scale:</TextBlock>
+                <TextBlock Name="ScaleText" Grid.Column="1" FontSize="14"></TextBlock>
+
+                <TextBlock Grid.Row="1" Margin="0,10,0,0" FontSize="14">Length:</TextBlock>
+                <TextBlock Name="DistanceText" Grid.Row="1" Grid.Column="1" Margin="0,10,0,0" FontSize="14"></TextBlock>
+
+                <TextBlock Grid.Row="2"  Margin="0,10,0,0" FontSize="14">Precision:</TextBlock>
+                <TextBlock Name="PrecisionText" Grid.Row="2" Grid.Column="1" Margin="0,10,0,0" FontSize="14"></TextBlock>
+
+                <TextBlock Grid.Row="3" Margin="0,10,0,0" FontSize="14">Angle:</TextBlock>
+                <TextBlock Name="AngleText" Grid.Row="3" Grid.Column="1" Margin="0,10,0,0" FontSize="14"></TextBlock>
+
+                <TextBlock Grid.Row="4" Margin="0,10,0,0" FontSize="14">X:</TextBlock>
+                <TextBlock Name="XText" Grid.Row="4" Grid.Column="1" Margin="0,10,0,0" FontSize="14"></TextBlock>
+
+                <TextBlock Grid.Row="5" Margin="0,10,0,0" FontSize="14">Y:</TextBlock>
+                <TextBlock Name="YText" Grid.Row="5" Grid.Column="1" Margin="0,10,0,0" FontSize="14"></TextBlock>
+
+            </Grid>
+
+            <Grid Name="PolyLinePanel" Grid.Row="1" Grid.Column="1" Margin="0,10,0,0" Visibility="Collapsed">
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition Width="80"></ColumnDefinition>
+                    <ColumnDefinition Width="auto"></ColumnDefinition>
+                </Grid.ColumnDefinitions>
+                <Grid.RowDefinitions>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                </Grid.RowDefinitions>
+                <TextBlock FontSize="14">Scale:</TextBlock>
+                <TextBlock Name="ScalePolyLineText" Grid.Column="1" FontSize="14"></TextBlock>
+
+                <TextBlock Grid.Row="1" Margin="0,10,0,0" FontSize="14">Length:</TextBlock>
+                <TextBlock Name="DistancePolyLineText" Grid.Row="1" Grid.Column="1" Margin="0,10,0,0" FontSize="14"></TextBlock>
+
+                <TextBlock Grid.Row="2"  Margin="0,10,0,0" FontSize="14">Precision:</TextBlock>
+                <TextBlock Name="PrecisionPolyLineText" Grid.Row="2" Grid.Column="1" Margin="0,10,0,0" FontSize="14"></TextBlock>
+
+                <TextBlock Grid.Row="3" Margin="0,10,0,0" FontSize="14">Angle:</TextBlock>
+                <TextBlock Name="AnglePolyLineText" Grid.Row="3" Grid.Column="1" Margin="0,10,0,0" FontSize="14"></TextBlock>
+
+            </Grid>
+
+            <Grid Name="PolygonPanel" Grid.Row="1" Grid.Column="1" Margin="0,10,0,0" Visibility="Collapsed">
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition Width="80"></ColumnDefinition>
+                    <ColumnDefinition Width="auto"></ColumnDefinition>
+                </Grid.ColumnDefinitions>
+                <Grid.RowDefinitions>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                </Grid.RowDefinitions>
+                <TextBlock FontSize="14">Scale:</TextBlock>
+                <TextBlock Name="ScalePolygonText" Grid.Column="1" FontSize="14"></TextBlock>
+
+                <TextBlock Grid.Row="1" Margin="0,10,0,0" FontSize="14">Area:</TextBlock>
+                <TextBlock Name="RoundPolygonText" Grid.Row="1" Grid.Column="1" Margin="0,10,0,0" FontSize="14"></TextBlock>
+
+                <TextBlock Grid.Row="2"  Margin="0,10,0,0" FontSize="14">Precision:</TextBlock>
+                <TextBlock Name="PrecisionPolygonText" Grid.Row="2" Grid.Column="1" Margin="0,10,0,0" FontSize="14"></TextBlock>
+
+                <TextBlock Grid.Row="3" Margin="0,10,0,0" FontSize="14">Angle:</TextBlock>
+                <TextBlock Name="AnglePolygonText" Grid.Row="3" Grid.Column="1" Margin="0,10,0,0" FontSize="14"></TextBlock>
+
+            </Grid>
+
+            <TextBlock Grid.Row="2" Grid.ColumnSpan="2" HorizontalAlignment="Right" 
+                       Margin="0,10,40,20" FontSize="14" Foreground="Blue" Cursor="Hand"
+                       MouseLeftButtonDown="TextBlock_MouseLeftButtonDown">Settings</TextBlock>
+
+        </Grid>
+    </Border>
+</UserControl>

+ 185 - 0
Demo/Examples/Compdfkit_Tools/Measure/MeasureInfoPanel.xaml.cs

@@ -0,0 +1,185 @@
+using ComPDFKit.Measure;
+using ComPDFKitViewer.AnnotEvent;
+using ComPDFKitViewer.PdfViewer;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing.Drawing2D;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Compdfkit_Tools.Measure
+{
+    /// <summary>
+    /// MeasureInfoPanel.xaml 的交互逻辑
+    /// </summary>
+    public partial class MeasureInfoPanel : UserControl
+    {
+        public event EventHandler SettingClick;
+        public CPDFMeasureType MeasureType { get; private set; }
+
+        internal Dictionary<string, string> IconsDict { get; private set; } = new Dictionary<string, string>()
+        {
+            {
+                "Distance Measurement",
+                "M17.7782 5.75646L14.2427 2.22093L13.0052 3.45837L15.4802 5.93333L14.4195 6.99399L11.9446 4.51903L10.1768 " +
+                "6.28679L12.6518 8.76175L11.5911 9.82241L9.11615 7.34745L7.34838 9.11522L9.82334 11.5902L8.76268 " +
+                "12.6508L6.28772 10.1759L4.51996 11.9436L6.99492 14.4186L5.93426 15.4793L3.4593 13.0043L2.22186 " +
+                "14.2417L5.75739 17.7773L17.7782 5.75646ZM15.3033 1.16027L14.2427 0.0996094L13.182 1.16027L1.1612 " +
+                "13.1811L0.100539 14.2417L1.1612 15.3024L4.69673 18.8379L5.75739 19.8986L6.81805 18.8379L18.8389 " +
+                "6.81712L19.8995 5.75646L18.8389 4.6958L15.3033 1.16027Z"
+            },
+            {
+                "Multiline",
+                "M0.5 3C0.5 1.89543 1.39543 1 2.5 1C3.33934 1 4.05793 1.51704 4.35462 2.25H15.6454C15.9421 1.51704 16.6607 1 " +
+                "17.5 1C18.6046 1 19.5 1.89543 19.5 3C19.5 3.83934 18.983 4.55793 18.25 4.85462V17V17.75H17.5H13.7011L14.5167 " +
+                "18.5765L13.5138 19.5928L11.4986 17.5505L10.9972 17.0423L11.4986 16.5342L13.5138 14.4918L14.5167 15.5082L13.7847 " +
+                "16.25H16.75V4.85462C16.2487 4.65168 15.8483 4.25135 15.6454 3.75H4.35462C4.15168 4.25135 3.75135 4.65168 3.25 " +
+                "4.85462V16.25H6.25V15H7.75V19H6.25V17.75H2.5H1.75V17V4.85462C1.01704 4.55793 0.5 3.83934 0.5 3Z"
+            },
+            {
+                "Polygonal",
+                "M1.37111 7.6963L10 1.42705L18.6289 7.6963L15.3329 17.8402H4.66705L1.37111 7.6963Z"
+            }
+
+        };
+
+        public MeasureInfoPanel()
+        {
+            InitializeComponent();
+        }
+
+        internal void SetMeasureScale(CPDFMeasureType measureType, string scale)
+        {
+            switch (measureType)
+            {
+                case CPDFMeasureType.CPDF_DISTANCE_MEASURE:
+                    ScaleText.Text = scale;
+                    break;
+                case CPDFMeasureType.CPDF_PERIMETER_MEASURE:
+                    ScalePolyLineText.Text = scale;
+                    break;
+                case CPDFMeasureType.CPDF_AREA_MEASURE:
+                    ScalePolygonText.Text = scale;
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        public void SetMeasureType(CPDFMeasureType newType)
+        {
+            MeasureType=newType;
+            int iconIndex = (int)newType;
+            LinePanel.Visibility = Visibility.Collapsed;
+            PolyLinePanel.Visibility = Visibility.Collapsed;
+            PolygonPanel.Visibility = Visibility.Collapsed;
+            if (iconIndex>=0 &&  iconIndex< IconsDict.Count)
+            {
+                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:
+                        LinePanel.Visibility = Visibility.Visible;
+                        MeasureIcon.Fill = new SolidColorBrush(Color.FromRgb(0x43, 0x47, 0x4D));
+                        MeasureIcon.Stroke = null;
+                        break;
+                    case CPDFMeasureType.CPDF_PERIMETER_MEASURE:
+                        PolyLinePanel.Visibility = Visibility.Visible;
+                        MeasureIcon.Fill = new SolidColorBrush(Color.FromRgb(0x43, 0x47, 0x4D));
+                        MeasureIcon.Stroke = null;
+                        break;
+                    case CPDFMeasureType.CPDF_AREA_MEASURE:
+                        PolygonPanel.Visibility = Visibility.Visible;
+                        MeasureIcon.Fill = null;
+                        MeasureIcon.Stroke=new SolidColorBrush(Color.FromRgb(0x43,0x47,0x4D));
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+
+        public void ClearMeasureInfo()
+        {
+            DistanceText.Text = string.Empty;
+            PrecisionText.Text = string.Empty;
+            AngleText.Text = string.Empty;
+            XText.Text = string.Empty;
+            YText.Text = string.Empty;
+            ScaleText.Text= string.Empty;
+            DistancePolyLineText.Text = string.Empty;
+            PrecisionPolyLineText.Text = string.Empty;
+            AnglePolyLineText.Text = string.Empty;
+            ScalePolyLineText.Text = string.Empty;
+            ScalePolygonText.Text=string.Empty;
+            RoundPolygonText.Text = string.Empty;
+            PrecisionPolygonText.Text = string.Empty;
+            AnglePolygonText.Text = string.Empty;
+        }
+
+        public void SetMeasureInfo(MeasureEventArgs info)
+        {
+            switch(info.Type)
+            {
+                case CPDFMeasureType.CPDF_DISTANCE_MEASURE:
+                    {
+                        DistanceText.Text=info.Distance;
+                        PrecisionText.Text= ((decimal)info.Precision).ToString();
+                        AngleText.Text = info.Angle.ToString()+"°";
+                        XText.Text=info.MousePos.X.ToString();
+                        YText.Text=info.MousePos.Y.ToString();
+                        ScaleText.Text = string.Format("{0} {1} = {2} {3}",
+                            info.RulerBase,
+                            info.RulerBaseUnit,
+                            info.RulerTranslate,
+                            info.RulerTranslateUnit);
+                    }
+                    break;
+                case CPDFMeasureType.CPDF_PERIMETER_MEASURE:
+                    {
+                        DistancePolyLineText.Text = info.Distance;
+                        PrecisionPolyLineText.Text = ((decimal)info.Precision).ToString();
+                        AnglePolyLineText.Text = info.Angle.ToString() + "°";
+                        ScalePolyLineText.Text = string.Format("{0} {1} = {2} {3}",
+                            info.RulerBase,
+                            info.RulerBaseUnit,
+                            info.RulerTranslate,
+                            info.RulerTranslateUnit);
+                    }
+                    break;
+                case CPDFMeasureType.CPDF_AREA_MEASURE:
+                    {
+                        RoundPolygonText.Text = info.Area;
+                        PrecisionPolygonText.Text = ((decimal)info.Precision).ToString();
+                        AnglePolygonText.Text = info.Angle.ToString() + "°";
+                        ScalePolygonText.Text = string.Format("{0} {1} = {2} {3}",
+                            info.RulerBase,
+                            info.RulerBaseUnit, 
+                            info.RulerTranslate,
+                            info.RulerTranslateUnit);
+                    }
+                    break;
+                default:
+                    break;
+            }
+        }
+        private void TextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+        {
+            SettingClick?.Invoke(this, e);
+        }
+    }
+}

+ 13 - 0
Demo/Examples/Compdfkit_Tools/Measure/MeasurePropertyControl.xaml

@@ -0,0 +1,13 @@
+<UserControl x:Class="Compdfkit_Tools.Measure.MeasurePropertyControl"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:Compdfkit_Tools.Measure"
+             mc:Ignorable="d" 
+             d:DesignHeight="450" d:DesignWidth="800" Background="#FAFCFF">
+    <Grid>
+        <TextBlock Name="NoResultText" Foreground="#43474D" FontSize="14" LineHeight="16" TextWrapping="Wrap" Width="190" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center">The property panel is empty</TextBlock>
+        <Border x:Name="MeasurePropertyPanel"></Border>
+    </Grid>
+</UserControl>

+ 100 - 0
Demo/Examples/Compdfkit_Tools/Measure/MeasurePropertyControl.xaml.cs

@@ -0,0 +1,100 @@
+using Compdfkit_Tools.Measure.Property;
+using Compdfkit_Tools.PDFControl;
+using ComPDFKitViewer.AnnotEvent;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Compdfkit_Tools.Measure
+{
+    /// <summary>
+    /// MeasurePropertyControl.xaml 的交互逻辑
+    /// </summary>
+    public partial class MeasurePropertyControl : UserControl
+    {
+        private UIElement currentPanel = null;
+        public MeasurePropertyControl()
+        {
+            InitializeComponent();
+        }
+
+        public void SetPropertyForMeasureCreate(AnnotHandlerEventArgs Args, AnnotAttribEvent attribEvent)
+        {
+            if (Args == null)
+            {
+                ClearMeasurePanel();
+                return;
+            }
+
+            switch (Args.EventType)
+            {
+                case AnnotArgsType.LineMeasure:
+                    StraightnessProperty straightnessProperty = new StraightnessProperty();
+                    if (attribEvent != null)
+                    {
+                        straightnessProperty.SetAnnotEventData(attribEvent);
+                    }
+                    else
+                    {
+                        straightnessProperty.SetAnnotArgsData((LineMeasureArgs)Args);
+                    }
+                    currentPanel = straightnessProperty;
+                    break;
+                case AnnotArgsType.PolyLineMeasure:
+                    MultilineProperty multilineProperty = new MultilineProperty();
+                    if (attribEvent != null)
+                    {
+                        multilineProperty.SetAnnotEventData(attribEvent);
+                    }
+                    else
+                    {
+                        multilineProperty.SetAnnotArgsData((PolyLineMeasureArgs)Args);
+                    }
+                    currentPanel = multilineProperty;
+                    break;
+                case AnnotArgsType.PolygonMeasure:
+                    PolygonalProperty polygonalProperty = new PolygonalProperty();
+                    if (attribEvent != null)
+                    {
+                        polygonalProperty.SetAnnotEventData(attribEvent);
+                    }
+                    else
+                    {
+                        polygonalProperty.SetAnnotArgsData((PolygonMeasureArgs)Args);
+                    }
+                    currentPanel = polygonalProperty;
+                    break;
+                default:
+                    break;
+            }
+            SetMeasurePanel(currentPanel);
+        }
+
+        private void SetMeasurePanel(UIElement newChild)
+        {
+            MeasurePropertyPanel.Child = newChild;
+        }
+
+        public void ClearMeasurePanel()
+        {
+            currentPanel = null;
+            MeasurePropertyPanel.Child = null;
+        }
+
+        public void SetPorpertyForMeasureModify(AnnotAttribEvent annotEvent)
+        {
+
+        }
+    }
+}

+ 100 - 0
Demo/Examples/Compdfkit_Tools/Measure/MeasureSettingDialog.xaml

@@ -0,0 +1,100 @@
+<Window x:Class="Compdfkit_Tools.Measure.MeasureSettingDialog"
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+        xmlns:local="clr-namespace:Compdfkit_Tools.Measure"
+        mc:Ignorable="d"
+        Title="MeasureSettingDialog" Height="350" Width="530" WindowStyle="None" WindowStartupLocation="CenterOwner"
+        ShowInTaskbar="False">
+    <Grid>
+        <Border BorderBrush="LightGray" CornerRadius="4" Background="White" Width="530" Height="350">
+            <Border.Effect>
+                <DropShadowEffect BlurRadius="20" ShadowDepth="0" Color="Black" Opacity="0.4"/>
+            </Border.Effect>
+
+            <Grid Margin="20">
+                <Grid.RowDefinitions>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                </Grid.RowDefinitions>
+                <TextBlock FontSize="16">Settings</TextBlock>
+
+                <Grid Grid.Row="1" Margin="0,20,0,0">
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="auto"></RowDefinition>
+                        <RowDefinition Height="auto"></RowDefinition>
+                        <RowDefinition Height="auto"></RowDefinition>
+                        <RowDefinition Height="auto"></RowDefinition>
+                        <RowDefinition Height="auto"></RowDefinition>
+                    </Grid.RowDefinitions>
+                    <TextBlock FontSize="14" FontWeight="Bold">Custom Scale</TextBlock>
+                    <TextBlock FontSize="14" Grid.Row="1" Margin="0,10,0,10">Drawing dimensions: Actual size</TextBlock>
+                    <StackPanel Grid.Row="2" Orientation="Horizontal">
+                        <TextBox Name="RulerBaseText" Width="110"  VerticalContentAlignment="Center" FontSize="14"
+                         InputMethod.IsInputMethodEnabled="False"
+                         PreviewKeyDown="TextBox_PreviewKeyDown"
+                         CommandManager.PreviewCanExecute="TextBox_CanExecute" MaxLength="6">
+
+                        </TextBox>
+                        <ComboBox Name="RulerBaseUnitCombo" Width="110" FontSize="14" Margin="10,0,0,0" VerticalContentAlignment="Center">
+                            <ComboBoxItem>in</ComboBoxItem>
+                            <ComboBoxItem IsSelected="True">cm</ComboBoxItem>
+                            <ComboBoxItem>mm</ComboBoxItem>
+                        </ComboBox>
+                        <TextBlock FontSize="14" Margin="10,0,10,0">=</TextBlock>
+                        <TextBox Name="RulerTranslateText" Width="110" FontSize="14" VerticalContentAlignment="Center"
+                         InputMethod.IsInputMethodEnabled="False"
+                         PreviewKeyDown="TextBox_PreviewKeyDown"
+                         CommandManager.PreviewCanExecute="TextBox_CanExecute" MaxLength="6">
+
+                        </TextBox>
+                        <ComboBox Name="RulerTranslateCombo" Width="110" FontSize="14" Margin="10,0,0,0" VerticalContentAlignment="Center">
+                            <ComboBoxItem>pt</ComboBoxItem>
+                            <ComboBoxItem IsSelected="True">cm</ComboBoxItem>
+                            <ComboBoxItem>in</ComboBoxItem>
+                            <ComboBoxItem>mm</ComboBoxItem>
+                            <ComboBoxItem>m</ComboBoxItem>
+                            <ComboBoxItem>km</ComboBoxItem>
+                            <ComboBoxItem>ft</ComboBoxItem>
+                            <ComboBoxItem>yd</ComboBoxItem>
+                            <ComboBoxItem>mi</ComboBoxItem>
+                        </ComboBox>
+                    </StackPanel>
+                    <TextBlock Grid.Row="3" Margin="0,10,0,10" FontSize="14">
+                Precision
+                    </TextBlock>
+                    <ComboBox Name="PrecisionBox" Grid.Row="4" Width="110" HorizontalAlignment="Left">
+                        <ComboBoxItem>1</ComboBoxItem>
+                        <ComboBoxItem >0.1</ComboBoxItem>
+                        <ComboBoxItem IsSelected="True">0.01</ComboBoxItem>
+                        <ComboBoxItem>0.001</ComboBoxItem>
+                        <ComboBoxItem>0.0001</ComboBoxItem>
+                    </ComboBox>
+                </Grid>
+
+                <Separator Grid.Row="2" Margin="0,10,0,10"></Separator>
+
+                <Grid Grid.Row="3" Visibility="Collapsed">
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="auto"></RowDefinition>
+                        <RowDefinition Height="auto"></RowDefinition>
+                        <RowDefinition Height="auto"></RowDefinition>
+                    </Grid.RowDefinitions>
+
+                    <TextBlock FontSize="14" >Show Caption</TextBlock>
+                    <CheckBox x:Name="LengthCheckBox" IsChecked="True" Grid.Row="1" Margin="0,10,0,10" FontSize="14">Length</CheckBox>
+                    <CheckBox x:Name="AreaCheckBox" IsChecked="True" Grid.Row="2" FontSize="14">Area</CheckBox>
+                </Grid>
+
+                <StackPanel Grid.Row="4" HorizontalAlignment="Right" Orientation="Horizontal">
+                    <Button Width="110" Height="32" Click="ButtonCancel_Click">Cancel</Button>
+                    <Button Width="110" Height="32" Click="ButtonDone_Click" Margin="10,0,0,0">Done</Button>
+                </StackPanel>
+            </Grid>
+        </Border>
+    </Grid>
+</Window>

+ 282 - 0
Demo/Examples/Compdfkit_Tools/Measure/MeasureSettingDialog.xaml.cs

@@ -0,0 +1,282 @@
+using ComPDFKit.Measure;
+using ComPDFKit.PDFAnnotation;
+using ComPDFKitViewer.AnnotEvent;
+using ComPDFKitViewer.PdfViewer;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace Compdfkit_Tools.Measure
+{
+    /// <summary>
+    /// MeasureSettingDialog.xaml 的交互逻辑
+    /// </summary>
+    public partial class MeasureSettingDialog : Window
+    {
+        public MeasureSettingDialog()
+        {
+            InitializeComponent();
+        }
+
+        public event EventHandler CancelEvent;
+        public event EventHandler DoneEvent;
+
+        public bool ReturnToInfoPanel { get; set; }
+
+        public List<AnnotHandlerEventArgs> UpdateArgsList { get; set; } = new List<AnnotHandlerEventArgs>();
+
+        private void ButtonCancel_Click(object sender, RoutedEventArgs e)
+        {
+            if (UpdateArgsList != null && UpdateArgsList.Count > 0)
+            {
+                ReturnToInfoPanel = false;
+            }
+            UpdateArgsList?.Clear();
+            CancelEvent?.Invoke(this, e);
+            ReturnToInfoPanel = false;
+            Close();
+        }
+
+        private void ButtonDone_Click(object sender, RoutedEventArgs e)
+        {
+            SaveMeasureSetting();
+            if (UpdateArgsList != null && UpdateArgsList.Count > 0)
+            {
+                List<AnnotArgsType> allowTypeList = new List<AnnotArgsType>()
+                {
+                    AnnotArgsType.LineMeasure,
+                    AnnotArgsType.PolyLineMeasure,
+                    AnnotArgsType.PolygonMeasure
+                };
+
+                foreach (AnnotHandlerEventArgs args in UpdateArgsList)
+                {
+                    if (allowTypeList.Contains(args.EventType))
+                    {
+                        CPDFAnnotation pdfAnnot = args.GetPDFAnnot();
+                        switch (pdfAnnot.Type)
+                        {
+                            case C_ANNOTATION_TYPE.C_ANNOTATION_LINE:
+                                {
+                                    CPDFLineAnnotation lineAnnot = (CPDFLineAnnotation)pdfAnnot;
+                                    if (lineAnnot.IsMersured())
+                                    {
+                                        CPDFDistanceMeasure lineMeasure = lineAnnot.GetDistanceMeasure();
+                                        CPDFMeasureInfo measureInfo = lineMeasure.MeasureInfo;
+                                        measureInfo.Precision = MeasureSetting.GetMeasureSavePrecision();
+                                        measureInfo.RulerBase = (float)MeasureSetting.RulerBase;
+                                        measureInfo.RulerBaseUnit = MeasureSetting.RulerBaseUnit;
+                                        measureInfo.RulerTranslate = (float)MeasureSetting.RulerTranslate;
+                                        measureInfo.RulerTranslateUnit = MeasureSetting.RulerTranslateUnit;
+                                        lineMeasure.SetMeasureInfo(measureInfo);
+                                        lineMeasure.SetMeasureScale(
+                                            measureInfo.RulerBase,
+                                            measureInfo.RulerBaseUnit,
+                                            measureInfo.RulerTranslate,
+                                            measureInfo.RulerTranslateUnit);
+                                        lineMeasure.UpdateAnnotMeasure();
+                                        lineAnnot.UpdateAp();
+                                        args.Draw();
+                                    }
+                                }
+                                break;
+                            case C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE:
+                                {
+                                    CPDFPolylineAnnotation polylineAnnot = (CPDFPolylineAnnotation)pdfAnnot;
+                                    if (polylineAnnot.IsMersured())
+                                    {
+                                        CPDFPerimeterMeasure polylineMeasure = polylineAnnot.GetPerimeterMeasure();
+                                        CPDFMeasureInfo measureInfo = polylineMeasure.MeasureInfo;
+                                        measureInfo.Precision = MeasureSetting.GetMeasureSavePrecision();
+                                        measureInfo.RulerBase = (float)MeasureSetting.RulerBase;
+                                        measureInfo.RulerBaseUnit = MeasureSetting.RulerBaseUnit;
+                                        measureInfo.RulerTranslate = (float)MeasureSetting.RulerTranslate;
+                                        measureInfo.RulerTranslateUnit = MeasureSetting.RulerTranslateUnit;
+                                        polylineMeasure.SetMeasureInfo(measureInfo);
+                                        polylineMeasure.SetMeasureScale(
+                                            measureInfo.RulerBase,
+                                            measureInfo.RulerBaseUnit,
+                                            measureInfo.RulerTranslate,
+                                            measureInfo.RulerTranslateUnit);
+                                        polylineMeasure.UpdateAnnotMeasure();
+                                        polylineAnnot.UpdateAp();
+                                        args.Draw();
+                                    }
+                                }
+                                break;
+                            case C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON:
+                                {
+                                    CPDFPolygonAnnotation areaAnnot = (CPDFPolygonAnnotation)pdfAnnot;
+                                    if (areaAnnot.IsMersured())
+                                    {
+                                        CPDFAreaMeasure areaMeasure = areaAnnot.GetAreaMeasure();
+                                        CPDFMeasureInfo measureInfo = areaMeasure.MeasureInfo;
+                                        measureInfo.Precision = MeasureSetting.GetMeasureSavePrecision();
+                                        measureInfo.RulerBase = (float)MeasureSetting.RulerBase;
+                                        measureInfo.RulerBaseUnit = MeasureSetting.RulerBaseUnit;
+                                        measureInfo.RulerTranslate = (float)MeasureSetting.RulerTranslate;
+                                        measureInfo.RulerTranslateUnit = MeasureSetting.RulerTranslateUnit;
+
+                                        measureInfo.CaptionType = CPDFCaptionType.CPDF_CAPTION_NONE;
+                                        if (MeasureSetting.IsShowArea)
+                                        {
+                                            measureInfo.CaptionType |= CPDFCaptionType.CPDF_CAPTION_AREA;
+                                        }
+                                        if (MeasureSetting.IsShowLength)
+                                        {
+                                            measureInfo.CaptionType |= CPDFCaptionType.CPDF_CAPTION_LENGTH;
+                                        }
+                                        areaMeasure.SetMeasureInfo(measureInfo);
+                                        areaMeasure.SetMeasureScale(
+                                            measureInfo.RulerBase,
+                                            measureInfo.RulerBaseUnit,
+                                            measureInfo.RulerTranslate,
+                                            measureInfo.RulerTranslateUnit);
+                                        areaMeasure.UpdateAnnotMeasure();
+                                        areaAnnot.UpdateAp();
+                                        args.Draw();
+                                    }
+                                }
+                                break;
+                            default:
+                                break;
+                        }
+                    }
+                }
+                ReturnToInfoPanel = false;
+            }
+            UpdateArgsList?.Clear();
+            DoneEvent?.Invoke(this, e);
+            ReturnToInfoPanel = false;
+            Close();
+        }
+
+        private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
+        {
+            List<Key> allowKeys = new List<Key>()
+            {
+                Key.Delete, Key.Back, Key.Enter, Key.NumPad0,  Key.NumPad1, Key.NumPad2, Key.NumPad3,
+                Key.NumPad4, Key.NumPad5, Key.NumPad6, Key.NumPad7, Key.NumPad8, Key.NumPad9, Key.D0,
+                Key.D1, Key.D2, Key.D3, Key.D4, Key.D5, Key.D6, Key.D7, Key.D8, Key.D9, Key.Left, Key.Right,
+                Key.OemPeriod,Key.Decimal
+            };
+
+            if (allowKeys.Contains(e.Key) == false)
+            {
+                e.Handled = true;
+            }
+        }
+
+        private void TextBox_CanExecute(object sender, CanExecuteRoutedEventArgs e)
+        {
+            try
+            {
+                if (e.Command == ApplicationCommands.Paste && Clipboard.ContainsText())
+                {
+                    string checkText = Clipboard.GetText();
+                    if (int.TryParse(checkText, out int value))
+                    {
+                        e.CanExecute = true;
+                    }
+                    e.Handled = true;
+                }
+            }
+            catch (Exception ex)
+            {
+
+            }
+        }
+
+        public void BindMeasureSetting()
+        {
+            RulerBaseText.Text = MeasureSetting.RulerBase.ToString();
+            RulerTranslateText.Text = MeasureSetting.RulerTranslate.ToString();
+            RulerTranslateCombo.SelectedIndex = -1;
+            RulerBaseUnitCombo.SelectedIndex = -1;
+            PrecisionBox.SelectedIndex = -1;
+            if (MeasureSetting.RulerBaseUnit == "in")
+            {
+                RulerBaseUnitCombo.SelectedIndex = 0;
+            }
+            if (MeasureSetting.RulerBaseUnit == "cm")
+            {
+                RulerBaseUnitCombo.SelectedIndex = 1;
+            }
+            if (MeasureSetting.RulerBaseUnit == "mm")
+            {
+                RulerBaseUnitCombo.SelectedIndex = 2;
+            }
+
+            for (int i = 0; i < RulerTranslateCombo.Items.Count; i++)
+            {
+                ComboBoxItem checkItem = RulerTranslateCombo.Items[i] as ComboBoxItem;
+                if (checkItem != null && checkItem.Content.ToString() == MeasureSetting.RulerTranslateUnit.ToString())
+                {
+                    RulerTranslateCombo.SelectedIndex = i;
+                }
+            }
+
+            for (int i = 0; i < PrecisionBox.Items.Count; i++)
+            {
+                ComboBoxItem checkItem = PrecisionBox.Items[i] as ComboBoxItem;
+                if (checkItem != null && checkItem.Content.ToString() == ((decimal)MeasureSetting.Precision).ToString())
+                {
+                    PrecisionBox.SelectedIndex = i;
+                }
+            }
+        }
+
+        private void SaveMeasureSetting()
+        {
+            if (double.TryParse(RulerBaseText.Text, out double ruleBase))
+            {
+                MeasureSetting.RulerBase = ruleBase;
+            }
+
+            if (RulerBaseUnitCombo.SelectedItem != null)
+            {
+                ComboBoxItem checkItem = RulerBaseUnitCombo.SelectedItem as ComboBoxItem;
+                MeasureSetting.RulerBaseUnit = checkItem.Content.ToString();
+            }
+
+            if (double.TryParse(RulerTranslateText.Text, out double ruletranBase))
+            {
+                MeasureSetting.RulerTranslate = ruletranBase;
+            }
+
+            if (RulerTranslateCombo.SelectedItem != null)
+            {
+                ComboBoxItem checkItem = RulerTranslateCombo.SelectedItem as ComboBoxItem;
+                MeasureSetting.RulerTranslateUnit = checkItem.Content.ToString();
+            }
+
+            if (PrecisionBox.SelectedValue != null)
+            {
+                ComboBoxItem checkItem = PrecisionBox.SelectedValue as ComboBoxItem;
+                if (double.TryParse(checkItem.Content.ToString(), out double precision))
+                {
+                    MeasureSetting.Precision = precision;
+                }
+            }
+
+            MeasureSetting.IsShowArea = (bool)AreaCheckBox.IsChecked;
+            MeasureSetting.IsShowLength = (bool)LengthCheckBox.IsChecked;
+        }
+
+        public void ChangedCheckBoxIsChecked(bool Area, bool Lenght)
+        {
+            AreaCheckBox.IsChecked = Area;
+            LengthCheckBox.IsChecked = Lenght;
+        }
+    }
+}

+ 97 - 0
Demo/Examples/Compdfkit_Tools/Measure/MeasureSettingPanel.xaml

@@ -0,0 +1,97 @@
+<UserControl x:Class="Compdfkit_Tools.Measure.MeasureSettingPanel"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:Compdfkit_Tools.Measure"
+             mc:Ignorable="d" 
+             d:DesignHeight="450" d:DesignWidth="800">
+    <Border x:Name="SettingPanel" BorderBrush="LightGray" CornerRadius="4" Background="White" Width="530" Height="350">
+        <Border.Effect>
+            <DropShadowEffect BlurRadius="20" ShadowDepth="0" Color="Black" Opacity="0.4"/>
+        </Border.Effect>
+
+        <Grid Margin="20">
+            <Grid.RowDefinitions>
+                <RowDefinition Height="auto"></RowDefinition>
+                <RowDefinition Height="auto"></RowDefinition>
+                <RowDefinition Height="auto"></RowDefinition>
+                <RowDefinition Height="auto"></RowDefinition>
+                <RowDefinition Height="auto"></RowDefinition>
+            </Grid.RowDefinitions>
+            <TextBlock FontSize="16">Settings</TextBlock>
+
+            <Grid Grid.Row="1" Margin="0,20,0,0">
+                <Grid.RowDefinitions>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                </Grid.RowDefinitions>
+                <TextBlock FontSize="14" FontWeight="Bold">Custom Scale</TextBlock>
+                <TextBlock FontSize="14" Grid.Row="1" Margin="0,10,0,10">Drawing dimensions: Actual size</TextBlock>
+                <StackPanel Grid.Row="2" Orientation="Horizontal">
+                    <TextBox Name="RulerBaseText" Width="110"  VerticalContentAlignment="Center" FontSize="14"
+                             InputMethod.IsInputMethodEnabled="False"
+                             PreviewKeyDown="TextBox_PreviewKeyDown"
+                             CommandManager.PreviewCanExecute="TextBox_CanExecute" MaxLength="6">
+                        
+                    </TextBox>
+                    <ComboBox Name="RulerBaseUnitCombo" Width="110" FontSize="14" Margin="10,0,0,0" VerticalContentAlignment="Center">
+                        <ComboBoxItem>in</ComboBoxItem>
+                        <ComboBoxItem IsSelected="True">cm</ComboBoxItem>
+                        <ComboBoxItem>mm</ComboBoxItem>
+                    </ComboBox>
+                    <TextBlock FontSize="14" Margin="10,0,10,0">=</TextBlock>
+                    <TextBox Name="RulerTranslateText" Width="110" FontSize="14" VerticalContentAlignment="Center"
+                             InputMethod.IsInputMethodEnabled="False"
+                             PreviewKeyDown="TextBox_PreviewKeyDown"
+                             CommandManager.PreviewCanExecute="TextBox_CanExecute" MaxLength="6">
+
+                    </TextBox>
+                    <ComboBox Name="RulerTranslateCombo" Width="110" FontSize="14" Margin="10,0,0,0" VerticalContentAlignment="Center">
+                        <ComboBoxItem>pt</ComboBoxItem>
+                        <ComboBoxItem IsSelected="True">cm</ComboBoxItem>
+                        <ComboBoxItem>in</ComboBoxItem>
+                        <ComboBoxItem>mm</ComboBoxItem>
+                        <ComboBoxItem>m</ComboBoxItem>
+                        <ComboBoxItem>km</ComboBoxItem>
+                        <ComboBoxItem>ft</ComboBoxItem>
+                        <ComboBoxItem>yd</ComboBoxItem>
+                        <ComboBoxItem>mi</ComboBoxItem>
+                    </ComboBox>
+                </StackPanel>
+                <TextBlock Grid.Row="3" Margin="0,10,0,10" FontSize="14">
+                    Precision
+                </TextBlock>
+                <ComboBox Name="PrecisionBox" Grid.Row="4" Width="110" HorizontalAlignment="Left">
+                    <ComboBoxItem>1</ComboBoxItem>
+                    <ComboBoxItem >0.1</ComboBoxItem>
+                    <ComboBoxItem IsSelected="True">0.01</ComboBoxItem>
+                    <ComboBoxItem>0.001</ComboBoxItem>
+                    <ComboBoxItem>0.0001</ComboBoxItem>
+                </ComboBox>
+            </Grid>
+            
+            <Separator Grid.Row="2" Margin="0,10,0,10"></Separator>
+
+            <Grid Grid.Row="3"  x:Name="AreaAndLength" Visibility="Collapsed">
+                <Grid.RowDefinitions>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                </Grid.RowDefinitions>
+
+                <TextBlock FontSize="14" >Show Caption</TextBlock>
+                <CheckBox x:Name="LengthCheckBox" IsChecked="True" Grid.Row="1" Margin="0,10,0,10" FontSize="14">Length</CheckBox>
+                <CheckBox x:Name="AreaCheckBox" IsChecked="True" Grid.Row="2" FontSize="14">Area</CheckBox>
+            </Grid>
+
+            <StackPanel Grid.Row="4" HorizontalAlignment="Right" Orientation="Horizontal">
+                <Button Width="110" Height="32" Click="ButtonCancel_Click">Cancel</Button>
+                <Button Width="110" Height="32" Click="ButtonDone_Click" Margin="10,0,0,0">Done</Button>
+            </StackPanel>
+        </Grid>
+    </Border>
+</UserControl>

+ 474 - 0
Demo/Examples/Compdfkit_Tools/Measure/MeasureSettingPanel.xaml.cs

@@ -0,0 +1,474 @@
+using ComPDFKit.Measure;
+using ComPDFKit.PDFAnnotation;
+using Compdfkit_Tools.PDFControl;
+using ComPDFKitViewer.AnnotEvent;
+using ComPDFKitViewer.PdfViewer;
+using System;
+using System.Collections.Generic;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+
+
+namespace Compdfkit_Tools.Measure
+{
+    /// <summary>
+    /// MeasureSettingPanel.xaml 的交互逻辑
+    /// </summary>
+    public partial class MeasureSettingPanel : UserControl
+    {
+        public event EventHandler CancelEvent;
+        public event EventHandler DoneEvent;
+
+        public PDFViewControl PdfViewControl {  get; set; } 
+
+        public bool ReturnToInfoPanel { get; set; }
+
+        public List<AnnotHandlerEventArgs> UpdateArgsList { get; set; } = new List<AnnotHandlerEventArgs>();
+        public MeasureSettingPanel()
+        {
+            InitializeComponent();
+        }
+
+        private void ButtonCancel_Click(object sender, RoutedEventArgs e)
+        {
+            if (UpdateArgsList != null && UpdateArgsList.Count > 0)
+            {
+                ReturnToInfoPanel = false;
+            }
+            UpdateArgsList?.Clear();
+            CancelEvent?.Invoke(this, e);
+            ReturnToInfoPanel = false;
+        }
+
+        public void ShowAreaAndLength(Visibility visibility)
+        {
+            if (visibility == Visibility.Visible)
+            {
+                SettingPanel.Height = 350;
+            }
+            else
+            {
+                SettingPanel.Height = 290;
+            }
+            AreaAndLength.Visibility = visibility;
+        }
+
+        private void ButtonDone_Click(object sender, RoutedEventArgs e)
+        {
+            if (string.IsNullOrEmpty(RulerBaseText.Text) || string.IsNullOrEmpty(RulerTranslateText.Text))
+            {
+                MessageBox.Show("Scale is not greater than zero");
+                return;
+            }
+            if (double.TryParse(RulerBaseText.Text, out double ruleBase))
+            {
+                if (ruleBase <= 0)
+                {
+                    MessageBox.Show("Scale is not greater than zero");
+                    return;
+                }
+            }
+
+            if (double.TryParse(RulerTranslateText.Text, out double ruletranBase))
+            {
+                if (ruletranBase <= 0)
+                {
+                    MessageBox.Show("Scale is not greater than zero");
+                    return;
+                }
+            }
+
+            if (UpdateArgsList != null && UpdateArgsList.Count == 0)
+            {
+                SaveMeasureSetting();
+            }
+
+            if (UpdateArgsList != null && UpdateArgsList.Count > 0)
+            {
+                List<AnnotArgsType> allowTypeList = new List<AnnotArgsType>()
+                {
+                    AnnotArgsType.LineMeasure,
+                    AnnotArgsType.PolyLineMeasure,
+                    AnnotArgsType.PolygonMeasure
+                };
+
+                foreach (AnnotHandlerEventArgs args in UpdateArgsList)
+                {
+                    if (allowTypeList.Contains(args.EventType))
+                    {
+                        CPDFAnnotation pdfAnnot = args.GetPDFAnnot();
+                        switch (pdfAnnot.Type)
+                        {
+                            case C_ANNOTATION_TYPE.C_ANNOTATION_LINE:
+                                {
+                                    CPDFLineAnnotation lineAnnot = (CPDFLineAnnotation)pdfAnnot;
+                                    if (lineAnnot.IsMersured())
+                                    {
+                                        CPDFDistanceMeasure lineMeasure = lineAnnot.GetDistanceMeasure();
+                                        CPDFMeasureInfo measureInfo = lineMeasure.MeasureInfo;
+                                        if (PrecisionBox.SelectedValue != null)
+                                        {
+                                            ComboBoxItem checkItem = PrecisionBox.SelectedValue as ComboBoxItem;
+                                            if (double.TryParse(checkItem.Content.ToString(), out double precision))
+                                            {
+                                                measureInfo.Precision = GetMeasureSavePrecision(precision);
+                                            }
+                                        }
+                                        if (double.TryParse(RulerBaseText.Text, out double ruleBasedata))
+                                        {
+                                            measureInfo.RulerBase = (float)ruleBasedata;
+                                        }
+                                        if (RulerBaseUnitCombo.SelectedItem != null)
+                                        {
+                                            ComboBoxItem RulerBaseUnitcheckItem = RulerBaseUnitCombo.SelectedItem as ComboBoxItem;
+                                            measureInfo.RulerBaseUnit = RulerBaseUnitcheckItem.Content.ToString();
+                                        }
+                                        if (double.TryParse(RulerTranslateText.Text, out double ruletranBasedata))
+                                        {
+                                            measureInfo.RulerTranslate = (float)ruletranBasedata;
+                                        }
+                                        if (RulerTranslateCombo.SelectedItem != null)
+                                        {
+                                            ComboBoxItem RulerTranslatecheckItem = RulerTranslateCombo.SelectedItem as ComboBoxItem;
+                                            measureInfo.RulerTranslateUnit = RulerTranslatecheckItem.Content.ToString();
+                                        }
+                                        lineMeasure.SetMeasureInfo(measureInfo);
+                                        lineMeasure.SetMeasureScale(
+                                            measureInfo.RulerBase,
+                                            measureInfo.RulerBaseUnit,
+                                            measureInfo.RulerTranslate,
+                                            measureInfo.RulerTranslateUnit);
+                                        lineMeasure.UpdateAnnotMeasure();
+                                        lineAnnot.UpdateAp();
+                                        args.Draw();
+                                        if (PdfViewControl != null && PdfViewControl.PDFView != null)
+                                        {
+                                            CPDFViewer viewer = PdfViewControl.PDFView;
+                                            if (viewer != null && viewer.UndoManager != null)
+                                            {
+                                                viewer.UndoManager.CanSave = true;
+                                            }
+                                        }
+                                    }
+                                }
+                                break;
+                            case C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE:
+                                {
+                                    CPDFPolylineAnnotation polylineAnnot = (CPDFPolylineAnnotation)pdfAnnot;
+                                    if (polylineAnnot.IsMersured())
+                                    {
+                                        CPDFPerimeterMeasure polylineMeasure = polylineAnnot.GetPerimeterMeasure();
+                                        CPDFMeasureInfo measureInfo = polylineMeasure.MeasureInfo;
+                                        if (PrecisionBox.SelectedValue != null)
+                                        {
+                                            ComboBoxItem checkItem = PrecisionBox.SelectedValue as ComboBoxItem;
+                                            if (double.TryParse(checkItem.Content.ToString(), out double precision))
+                                            {
+                                                measureInfo.Precision = GetMeasureSavePrecision(precision);
+                                            }
+                                        }
+                                        if (double.TryParse(RulerBaseText.Text, out double ruleBasedata))
+                                        {
+                                            measureInfo.RulerBase = (float)ruleBasedata;
+                                        }
+                                        if (RulerBaseUnitCombo.SelectedItem != null)
+                                        {
+                                            ComboBoxItem RulerBaseUnitcheckItem = RulerBaseUnitCombo.SelectedItem as ComboBoxItem;
+                                            measureInfo.RulerBaseUnit = RulerBaseUnitcheckItem.Content.ToString();
+                                        }
+                                        if (double.TryParse(RulerTranslateText.Text, out double ruletranBasedata))
+                                        {
+                                            measureInfo.RulerTranslate = (float)ruletranBasedata;
+                                        }
+                                        if (RulerTranslateCombo.SelectedItem != null)
+                                        {
+                                            ComboBoxItem RulerTranslatecheckItem = RulerTranslateCombo.SelectedItem as ComboBoxItem;
+                                            measureInfo.RulerTranslateUnit = RulerTranslatecheckItem.Content.ToString();
+                                        }
+                                        polylineMeasure.SetMeasureInfo(measureInfo);
+                                        polylineMeasure.SetMeasureScale(
+                                            measureInfo.RulerBase,
+                                            measureInfo.RulerBaseUnit,
+                                            measureInfo.RulerTranslate,
+                                            measureInfo.RulerTranslateUnit);
+                                        polylineMeasure.UpdateAnnotMeasure();
+                                        polylineAnnot.UpdateAp();
+                                        args.Draw();
+                                        if (PdfViewControl != null && PdfViewControl.PDFView != null)
+                                        {
+                                            CPDFViewer viewer = PdfViewControl.PDFView;
+                                            if (viewer != null && viewer.UndoManager != null)
+                                            {
+                                                viewer.UndoManager.CanSave = true;
+                                            }
+                                        }
+                                    }
+                                }
+                                break;
+                            case C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON:
+                                {
+                                    CPDFPolygonAnnotation areaAnnot = (CPDFPolygonAnnotation)pdfAnnot;
+                                    if (areaAnnot.IsMersured())
+                                    {
+                                        CPDFAreaMeasure areaMeasure = areaAnnot.GetAreaMeasure();
+                                        CPDFMeasureInfo measureInfo = areaMeasure.MeasureInfo;
+                                        if (PrecisionBox.SelectedValue != null)
+                                        {
+                                            ComboBoxItem checkItem = PrecisionBox.SelectedValue as ComboBoxItem;
+                                            if (double.TryParse(checkItem.Content.ToString(), out double precision))
+                                            {
+                                                measureInfo.Precision = GetMeasureSavePrecision(precision);
+                                            }
+                                        }
+                                        if (double.TryParse(RulerBaseText.Text, out double ruleBasedata))
+                                        {
+                                            measureInfo.RulerBase = (float)ruleBasedata;
+                                        }
+                                        if (RulerBaseUnitCombo.SelectedItem != null)
+                                        {
+                                            ComboBoxItem RulerBaseUnitcheckItem = RulerBaseUnitCombo.SelectedItem as ComboBoxItem;
+                                            measureInfo.RulerBaseUnit = RulerBaseUnitcheckItem.Content.ToString();
+                                        }
+                                        if (double.TryParse(RulerTranslateText.Text, out double ruletranBasedata))
+                                        {
+                                            measureInfo.RulerTranslate = (float)ruletranBasedata;
+                                        }
+                                        if (RulerTranslateCombo.SelectedItem != null)
+                                        {
+                                            ComboBoxItem RulerTranslatecheckItem = RulerTranslateCombo.SelectedItem as ComboBoxItem;
+                                            measureInfo.RulerTranslateUnit = RulerTranslatecheckItem.Content.ToString();
+                                        }
+
+                                        measureInfo.CaptionType = CPDFCaptionType.CPDF_CAPTION_NONE;
+                                        if ((bool)AreaCheckBox.IsChecked)
+                                        {
+                                            measureInfo.CaptionType |= CPDFCaptionType.CPDF_CAPTION_AREA;
+                                        }
+                                        if ((bool)LengthCheckBox.IsChecked)
+                                        {
+                                            measureInfo.CaptionType |= CPDFCaptionType.CPDF_CAPTION_LENGTH;
+                                        }
+                                        areaMeasure.SetMeasureInfo(measureInfo);
+                                        areaMeasure.SetMeasureScale(
+                                            measureInfo.RulerBase,
+                                            measureInfo.RulerBaseUnit,
+                                            measureInfo.RulerTranslate,
+                                            measureInfo.RulerTranslateUnit);
+                                        areaMeasure.UpdateAnnotMeasure();
+                                        areaAnnot.UpdateAp();
+                                        args.Draw();
+                                        if(PdfViewControl!=null && PdfViewControl.PDFView!=null)
+                                        {
+                                            CPDFViewer viewer = PdfViewControl.PDFView;
+                                            if(viewer!=null && viewer.UndoManager!=null)
+                                            {
+                                                viewer.UndoManager.CanSave = true;
+                                            }
+                                        }
+                                    }
+                                }
+                                break;
+                            default:
+                                break;
+                        }
+                    }
+                }
+                ReturnToInfoPanel = false;
+            }
+            UpdateArgsList?.Clear();
+            DoneEvent?.Invoke(this, e);
+            ReturnToInfoPanel = false;
+        }
+
+        private int GetMeasureSavePrecision(double Precision)
+        {
+            if (Precision == 1)
+            {
+                return CPDFMeasure.PRECISION_VALUE_ZERO;
+            }
+            if (Precision == 0.1)
+            {
+                return CPDFMeasure.PRECISION_VALUE_ONE;
+            }
+            if (Precision == 0.01)
+            {
+                return CPDFMeasure.PRECISION_VALUE_TWO;
+            }
+            if (Precision == 0.001)
+            {
+                return CPDFMeasure.PRECISION_VALUE_THREE;
+            }
+            if (Precision == 0.0001)
+            {
+                return CPDFMeasure.PRECISION_VALUE_FOUR;
+            }
+            return 0;
+        }
+
+        private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
+        {
+            List<Key> allowKeys = new List<Key>()
+            {
+                Key.Delete, Key.Back, Key.Enter, Key.NumPad0,  Key.NumPad1, Key.NumPad2, Key.NumPad3,
+                Key.NumPad4, Key.NumPad5, Key.NumPad6, Key.NumPad7, Key.NumPad8, Key.NumPad9, Key.D0,
+                Key.D1, Key.D2, Key.D3, Key.D4, Key.D5, Key.D6, Key.D7, Key.D8, Key.D9, Key.Left, Key.Right,
+                Key.OemPeriod,Key.Decimal
+            };
+
+            if (allowKeys.Contains(e.Key) == false)
+            {
+                e.Handled = true;
+            }
+        }
+
+        private void TextBox_CanExecute(object sender, CanExecuteRoutedEventArgs e)
+        {
+            try
+            {
+                if (e.Command == ApplicationCommands.Paste && Clipboard.ContainsText())
+                {
+                    string checkText = Clipboard.GetText();
+                    if (int.TryParse(checkText, out int value))
+                    {
+                        e.CanExecute = true;
+                    }
+                    e.Handled = true;
+                }
+            }
+            catch (Exception ex)
+            {
+
+            }
+        }
+
+        public void BindMeasureSetting()
+        {
+            if (UpdateArgsList != null && UpdateArgsList.Count>0)
+            {
+                return;
+            }
+            RulerBaseText.Text = MeasureSetting.RulerBase.ToString();
+            RulerTranslateText.Text = MeasureSetting.RulerTranslate.ToString();
+            RulerTranslateCombo.SelectedIndex = -1;
+            RulerBaseUnitCombo.SelectedIndex = -1;
+            PrecisionBox.SelectedIndex = -1;
+            if (MeasureSetting.RulerBaseUnit == "in")
+            {
+                RulerBaseUnitCombo.SelectedIndex = 0;
+            }
+            if (MeasureSetting.RulerBaseUnit == "cm")
+            {
+                RulerBaseUnitCombo.SelectedIndex = 1;
+            }
+            if (MeasureSetting.RulerBaseUnit == "mm")
+            {
+                RulerBaseUnitCombo.SelectedIndex = 2;
+            }
+
+            for (int i = 0; i < RulerTranslateCombo.Items.Count; i++)
+            {
+                ComboBoxItem checkItem = RulerTranslateCombo.Items[i] as ComboBoxItem;
+                if (checkItem != null && checkItem.Content.ToString() == MeasureSetting.RulerTranslateUnit.ToString())
+                {
+                    RulerTranslateCombo.SelectedIndex = i;
+                }
+            }
+
+            for (int i = 0; i < PrecisionBox.Items.Count; i++)
+            {
+                ComboBoxItem checkItem = PrecisionBox.Items[i] as ComboBoxItem;
+                if (checkItem != null && checkItem.Content.ToString() == ((decimal)MeasureSetting.Precision).ToString())
+                {
+                    PrecisionBox.SelectedIndex = i;
+                }
+            }
+        }
+        public void BindMeasureSetting(MeasureEventArgs measureEventArgs)
+        {
+            if (measureEventArgs != null)
+            {
+
+                RulerBaseText.Text = measureEventArgs.RulerBase.ToString();
+                RulerTranslateText.Text = measureEventArgs.RulerTranslate.ToString();
+                RulerTranslateCombo.SelectedIndex = -1;
+                RulerBaseUnitCombo.SelectedIndex = -1;
+                PrecisionBox.SelectedIndex = -1;
+                if (measureEventArgs.RulerBaseUnit == "in")
+                {
+                    RulerBaseUnitCombo.SelectedIndex = 0;
+                }
+                if (measureEventArgs.RulerBaseUnit == "cm")
+                {
+                    RulerBaseUnitCombo.SelectedIndex = 1;
+                }
+                if (measureEventArgs.RulerBaseUnit == "mm")
+                {
+                    RulerBaseUnitCombo.SelectedIndex = 2;
+                }
+
+                for (int i = 0; i < RulerTranslateCombo.Items.Count; i++)
+                {
+                    ComboBoxItem checkItem = RulerTranslateCombo.Items[i] as ComboBoxItem;
+                    if (checkItem != null && checkItem.Content.ToString() == measureEventArgs.RulerTranslateUnit.ToString())
+                    {
+                        RulerTranslateCombo.SelectedIndex = i;
+                    }
+                }
+
+                for (int i = 0; i < PrecisionBox.Items.Count; i++)
+                {
+                    ComboBoxItem checkItem = PrecisionBox.Items[i] as ComboBoxItem;
+                    if (checkItem != null && checkItem.Content.ToString() == ((decimal)measureEventArgs.Precision).ToString())
+                    {
+                        PrecisionBox.SelectedIndex = i;
+                    }
+                }
+            }
+        }
+
+        private void SaveMeasureSetting()
+        {
+            if (double.TryParse(RulerBaseText.Text, out double ruleBase))
+            {
+                MeasureSetting.RulerBase = ruleBase;
+            }
+
+            if (RulerBaseUnitCombo.SelectedItem != null)
+            {
+                ComboBoxItem checkItem = RulerBaseUnitCombo.SelectedItem as ComboBoxItem;
+                MeasureSetting.RulerBaseUnit = checkItem.Content.ToString();
+            }
+
+            if (double.TryParse(RulerTranslateText.Text, out double ruletranBase))
+            {
+                MeasureSetting.RulerTranslate = ruletranBase;
+            }
+
+            if (RulerTranslateCombo.SelectedItem != null)
+            {
+                ComboBoxItem checkItem = RulerTranslateCombo.SelectedItem as ComboBoxItem;
+                MeasureSetting.RulerTranslateUnit = checkItem.Content.ToString();
+            }
+
+            if (PrecisionBox.SelectedValue != null)
+            {
+                ComboBoxItem checkItem = PrecisionBox.SelectedValue as ComboBoxItem;
+                if (double.TryParse(checkItem.Content.ToString(), out double precision))
+                {
+                    MeasureSetting.Precision = precision;
+                }
+            }
+
+            MeasureSetting.IsShowArea = (bool)AreaCheckBox.IsChecked;
+            MeasureSetting.IsShowLength = (bool)LengthCheckBox.IsChecked;
+        }
+
+        public void ChangedCheckBoxIsChecked(bool Area, bool Lenght)
+        {
+            AreaCheckBox.IsChecked = Area;
+            LengthCheckBox.IsChecked = Lenght;
+        }
+    }
+}
+

+ 70 - 0
Demo/Examples/Compdfkit_Tools/Measure/Property/MultilineProperty.xaml

@@ -0,0 +1,70 @@
+<UserControl x:Class="Compdfkit_Tools.Measure.Property.MultilineProperty"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:Compdfkit_Tools.Measure.Property" xmlns:cpdfcommon="clr-namespace:Compdfkit_Tools.Common" xmlns:cpdftools="clr-namespace:Compdfkit_Tools.PDFControl"
+             mc:Ignorable="d" 
+             Loaded="UserControl_Loaded"
+             Unloaded="UserControl_Unloaded"
+             >
+    <UserControl.Resources>
+        <ResourceDictionary>
+            <ResourceDictionary.MergedDictionaries>
+                <ResourceDictionary Source="../../Asset/Styles/ComboBoxStyle.xaml"></ResourceDictionary>
+            </ResourceDictionary.MergedDictionaries>
+        </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="Appearance"  HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16" FontWeight="Bold" FontFamily="Segoe UI"></TextBlock>
+                    </Grid>
+                </Border>
+                <StackPanel Height="68" Margin="5">
+                    <TextBlock Text="Line Color" FontWeight="SemiBold" FontSize="14" LineHeight="16"  FontFamily="Segoe UI"/>
+                    <cpdfcommon:ColorPickerControl x:Name="BorderColorPickerControl" Margin="0,8,0,0" Brush="Red" TransparentBtnProperty ="Collapsed" ColorChanged="BorderColorPickerControl_ColorChanged"/>
+                </StackPanel>
+                <StackPanel Height="68" Margin="5">
+                    <TextBlock Text="Opacity" FontWeight="SemiBold" FontSize="14" LineHeight="16"  FontFamily="Segoe UI"/>
+                    <cpdfcommon:CPDFOpacityControl x:Name="CPDFOpacityControl" Margin="0,8,0,0" OpacityChanged="CPDFOpacityControl_OpacityChanged"/>
+                </StackPanel>
+                <StackPanel Height="68" Margin="5">
+                    <TextBlock Text="Line Width" FontWeight="SemiBold" FontSize="14" LineHeight="16"  FontFamily="Segoe UI"/>
+                    <cpdfcommon:CPDFThicknessControl x:Name="CPDFThicknessControl" Margin="0,8,0,0" ThicknessChanged="CPDFThicknessControl_ThicknessChanged"/>
+                </StackPanel>
+                <StackPanel x:Name="LineStyleStackPanel" Height="90" Margin="5">
+                    <TextBlock Text="Line and Border Style" FontWeight="SemiBold" FontSize="14" LineHeight="16"  FontFamily="Segoe UI"/>
+                    <cpdfcommon:CPDFLineStyleControl x:Name="CPDFLineStyleControl" Margin="0,8,0,0" LineStyleChanged="CPDFLineStyleControl_LineStyleChanged"/>
+                </StackPanel>
+                <StackPanel x:Name="FontColorStackPanel" Height="75" Margin="5">
+                    <TextBlock Text="Font Color" FontWeight="SemiBold" FontSize="14" LineHeight="16"  FontFamily="Segoe UI"/>
+                    <cpdfcommon:ColorPickerControl Margin="0,8,0,0" x:Name="FontColorPickerControl" TransparentBtnProperty ="Collapsed" Brush="Transparent" ColorChanged="FontColorPickerControl_ColorChanged"/>
+                </StackPanel>
+                <StackPanel  Margin="5">
+                    <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="Text" FontSize="14" FontFamily="Segoe UI" FontWeight="Bold" />
+                    <ComboBox x:Name="FontCombox" Margin="0,8,0,0" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FontCombox_SelectionChanged">
+                        <ComboBoxItem Content="Arial"/>
+                        <ComboBoxItem Content="Courier New"/>
+                        <ComboBoxItem Content="Times New Roman"/>
+                    </ComboBox>
+                    <StackPanel Orientation="Horizontal" >
+                        <ComboBox x:Name="FontStyleCombox"  Margin="0,8,0,0" Width="148" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FontStyleCombox_SelectionChanged">
+                            <ComboBoxItem Content="Regular"/>
+                            <ComboBoxItem Content="Bold"/>
+                            <ComboBoxItem Content="Italic"/>
+                            <ComboBoxItem Content="Bold Italic"/>
+                        </ComboBox>
+                        <ComboBox x:Name="FontSizeComboBox" Margin="4,8,0,0" Width="72" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FontSizeCombox_SelectionChanged"/>
+                    </StackPanel>
+                </StackPanel>
+                <StackPanel Height="160" Margin="5">
+                    <TextBlock Text="Note"></TextBlock>
+                    <TextBox Height="100"  x:Name="NoteTextBox"  TextChanged="NoteTextBox_TextChanged" TextWrapping="Wrap" AcceptsReturn="True"></TextBox>
+                </StackPanel>
+            </StackPanel>
+        </Grid>
+    </ScrollViewer>
+</UserControl>

+ 293 - 0
Demo/Examples/Compdfkit_Tools/Measure/Property/MultilineProperty.xaml.cs

@@ -0,0 +1,293 @@
+using ComPDFKit.PDFAnnotation;
+using Compdfkit_Tools.Data;
+using ComPDFKitViewer;
+using ComPDFKitViewer.AnnotEvent;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Compdfkit_Tools.Measure.Property
+{
+    /// <summary>
+    /// MultilineProperty.xaml 的交互逻辑
+    /// </summary>
+    public partial class MultilineProperty : UserControl
+    {
+        private AnnotAttribEvent MultilineEvent { get; set; }
+
+        public ObservableCollection<int> SizeList { get; set; } = new ObservableCollection<int>
+        {
+            6,8,9,10,12,14,18,20,24,26,28,32,30,32,48,72
+        };
+
+        bool IsLoadedData = false;
+
+        public MultilineProperty()
+        {
+            InitializeComponent();
+        }
+
+        private void NoteTextBox_TextChanged(object sender, TextChangedEventArgs e)
+        {
+            if (IsLoadedData)
+            {
+                MultilineEvent?.UpdateAttrib(AnnotAttrib.NoteText, NoteTextBox.Text);
+                MultilineEvent?.UpdateAnnot();
+            }
+        }
+
+        private void FontStyleCombox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+            if (IsLoadedData)
+            {
+                int selectIndex = Math.Max(0, FontStyleCombox.SelectedIndex);
+                bool isBold = false;
+                bool isItalic = false;
+
+                switch (selectIndex)
+                {
+                    case 0:
+                        isBold = false;
+                        isItalic = false;
+                        break;
+                    case 1:
+                        isBold = true;
+                        isItalic = false;
+                        break;
+                    case 2:
+                        isBold = false;
+                        isItalic = true;
+                        break;
+                    case 3:
+                        isBold = true;
+                        isItalic = true;
+                        break;
+                    default:
+                        break;
+                }
+                MultilineEvent?.UpdateAttrib(AnnotAttrib.IsBold, isBold);
+                MultilineEvent?.UpdateAttrib(AnnotAttrib.IsItalic, isItalic);
+                MultilineEvent?.UpdateAnnot();
+            }
+        }
+
+        private void FontCombox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+            ComboBoxItem selectItem = FontCombox.SelectedItem as ComboBoxItem;
+            if (selectItem != null && selectItem.Content != null)
+            {
+                MultilineEvent?.UpdateAttrib(AnnotAttrib.FontName, selectItem.Content.ToString());
+                MultilineEvent?.UpdateAnnot();
+            }
+        }
+
+        private void FontSizeCombox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+            if (IsLoadedData)
+            {
+                MultilineEvent?.UpdateAttrib(AnnotAttrib.FontSize, (sender as ComboBox).SelectedItem);
+                MultilineEvent?.UpdateAnnot();
+            }
+        }
+
+        private void BorderColorPickerControl_ColorChanged(object sender, EventArgs e)
+        {
+            SolidColorBrush checkBrush = BorderColorPickerControl.GetBrush() as SolidColorBrush;
+            if (checkBrush != null)
+            {
+                MultilineEvent?.UpdateAttrib(AnnotAttrib.Color, checkBrush.Color);
+                MultilineEvent?.UpdateAnnot();
+            }
+        }
+
+        private void CPDFOpacityControl_OpacityChanged(object sender, EventArgs e)
+        {
+            if (IsLoadedData)
+            {
+                MultilineEvent?.UpdateAttrib(AnnotAttrib.Transparency, CPDFOpacityControl.OpacityValue / 100D);
+                MultilineEvent?.UpdateAnnot();
+            }
+        }
+
+        private void CPDFThicknessControl_ThicknessChanged(object sender, EventArgs e)
+        {
+            if (IsLoadedData)
+            {
+                MultilineEvent?.UpdateAttrib(AnnotAttrib.Thickness, CPDFThicknessControl.Thickness);
+                MultilineEvent?.UpdateAnnot();
+            }
+        }
+
+        private void CPDFLineStyleControl_LineStyleChanged(object sender, EventArgs e)
+        {
+                MultilineEvent?.UpdateAttrib(AnnotAttrib.LineStyle, CPDFLineStyleControl.DashStyle);
+                MultilineEvent?.UpdateAnnot();
+        }
+
+        private void FontColorPickerControl_ColorChanged(object sender, EventArgs e)
+        {
+            SolidColorBrush checkBrush = FontColorPickerControl.GetBrush() as SolidColorBrush;
+            if (checkBrush != null)
+            {
+                MultilineEvent?.UpdateAttrib(AnnotAttrib.FontColor, checkBrush.Color);
+                MultilineEvent?.UpdateAnnot();
+            }
+        }
+
+        public void SetAnnotArgsData(PolyLineMeasureArgs annotArgs)
+        {
+            Dictionary<AnnotAttrib, object> attribDict = new Dictionary<AnnotAttrib, object>();
+            attribDict[AnnotAttrib.Color] = annotArgs.LineColor;
+            attribDict[AnnotAttrib.Transparency] = annotArgs.Transparency;
+            attribDict[AnnotAttrib.Thickness] = annotArgs.LineWidth;
+            attribDict[AnnotAttrib.LineStyle] = annotArgs.LineDash;
+            attribDict[AnnotAttrib.FontColor] = annotArgs.FontColor;
+            attribDict[AnnotAttrib.FontName] = annotArgs.FontName;
+            attribDict[AnnotAttrib.IsBold] = annotArgs.IsBold;
+            attribDict[AnnotAttrib.IsItalic] = annotArgs.IsItalic;
+            attribDict[AnnotAttrib.FontSize] = annotArgs.FontSize;
+            attribDict[AnnotAttrib.NoteText] = annotArgs.Content;
+
+            AnnotAttribEvent annotEvent = AnnotAttribEvent.GetAnnotAttribEvent(annotArgs, attribDict);
+            SetAnnotEventData(annotEvent);
+        }
+
+        public void SetAnnotEventData(AnnotAttribEvent annotEvent)
+        {
+            MultilineEvent = null;
+            if (annotEvent != null)
+            {
+                foreach (AnnotAttrib attrib in annotEvent.Attribs.Keys)
+                {
+                    switch (attrib)
+                    {
+                        case AnnotAttrib.Color:
+                            BorderColorPickerControl.SetCheckedForColor((Color)annotEvent.Attribs[attrib]);
+                            break;
+                        case AnnotAttrib.Transparency:
+                            double transparennt = Convert.ToDouble(annotEvent.Attribs[attrib]);
+                            if (transparennt > 1)
+                            {
+                                transparennt = (transparennt / 255D);
+                            }
+                            CPDFOpacityControl.OpacityValue = (int)(transparennt * 100);
+                            break;
+                        case AnnotAttrib.Thickness:
+                            CPDFThicknessControl.Thickness = Convert.ToInt16(annotEvent.Attribs[attrib]);
+                            break;
+                        case AnnotAttrib.LineStyle:
+                            CPDFLineStyleControl.DashStyle = (DashStyle)(annotEvent.Attribs[attrib]);
+                            break;
+                        case AnnotAttrib.FontColor:
+                            FontColorPickerControl.SetCheckedForColor((Color)annotEvent.Attribs[attrib]);
+                            break;
+                        case AnnotAttrib.FontName:
+                            {
+                                string fontName = (string)annotEvent.Attribs[AnnotAttrib.FontName];
+                                if (fontName.Contains("Courier"))
+                                {
+                                    FontCombox.SelectedIndex = 1;
+                                }
+                                else if (fontName == "Arial" || fontName.Contains("Helvetica"))
+                                {
+                                    FontCombox.SelectedIndex = 0;
+
+                                }
+                                else if (fontName.Contains("Times"))
+                                {   
+                                    FontCombox.SelectedIndex = 2;
+                                }
+                                else
+                                {
+                                    FontCombox.SelectedIndex = -1;
+                                }
+                            }
+                            break;
+                        case AnnotAttrib.FontSize:
+                            SetFontSize(Convert.ToDouble(annotEvent.Attribs[attrib]));
+                            break;
+                        case AnnotAttrib.NoteText:
+                            NoteTextBox.Text = annotEvent.Attribs[attrib].ToString();
+                            break;
+                        default:
+                            break;
+                    }
+                }
+
+
+                bool isBold = false;
+                bool isItalic = false;
+                if (annotEvent.Attribs.ContainsKey(AnnotAttrib.IsBold))
+                {
+                    isBold = (bool)annotEvent.Attribs[AnnotAttrib.IsBold];
+                }
+                if (annotEvent.Attribs.ContainsKey(AnnotAttrib.IsItalic))
+                {
+                    isItalic = (bool)annotEvent.Attribs[AnnotAttrib.IsItalic];
+                }
+
+                SetFontStyle(isBold, isItalic);
+            }
+
+            MultilineEvent = annotEvent;
+        }
+
+        public void SetFontStyle(bool isBold, bool isItalic)
+        {
+            if (isBold == false && isItalic == false)
+            {
+                FontStyleCombox.SelectedIndex = 0;
+                return;
+            }
+
+            if (isBold && isItalic == false)
+            {
+                FontStyleCombox.SelectedIndex = 1;
+                return;
+            }
+
+            if (isBold == false && isItalic)
+            {
+                FontStyleCombox.SelectedIndex = 2;
+                return;
+            }
+
+            if (isBold && isItalic)
+            {
+                FontStyleCombox.SelectedIndex = 3;
+            }
+        }
+
+        private void SetFontSize(double size)
+        {
+            int index = SizeList.IndexOf((int)size);
+            FontSizeComboBox.SelectedIndex = index;
+        }
+
+        private void UserControl_Loaded(object sender, RoutedEventArgs e)
+        {
+            Binding SizeListbinding = new Binding();
+            SizeListbinding.Source = this;
+            SizeListbinding.Path = new System.Windows.PropertyPath("SizeList");
+            FontSizeComboBox.SetBinding(ComboBox.ItemsSourceProperty, SizeListbinding);
+            IsLoadedData = true;
+        }
+
+        private void UserControl_Unloaded(object sender, RoutedEventArgs e)
+        {
+            IsLoadedData = false;
+        }
+    }
+}

+ 70 - 0
Demo/Examples/Compdfkit_Tools/Measure/Property/PolygonalProperty.xaml

@@ -0,0 +1,70 @@
+<UserControl x:Class="Compdfkit_Tools.Measure.Property.PolygonalProperty"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:Compdfkit_Tools.Measure.Property" xmlns:cpdftools="clr-namespace:Compdfkit_Tools.PDFControl" xmlns:cpdfcommon="clr-namespace:Compdfkit_Tools.Common"
+             mc:Ignorable="d" 
+             Loaded="UserControl_Loaded"
+             Unloaded="UserControl_Unloaded"
+             >
+    <UserControl.Resources>
+        <ResourceDictionary>
+            <ResourceDictionary.MergedDictionaries>
+                <ResourceDictionary Source="../../Asset/Styles/ComboBoxStyle.xaml"></ResourceDictionary>
+            </ResourceDictionary.MergedDictionaries>
+        </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="Appearance"  HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16"  FontWeight="Bold" FontFamily="Segoe UI"></TextBlock>
+                    </Grid>
+                </Border>
+                <StackPanel Height="68" Margin="5">
+                    <TextBlock Text="Fill Color"  FontWeight="SemiBold" FontSize="14" LineHeight="16"  FontFamily="Segoe UI"/>
+                    <cpdfcommon:ColorPickerControl x:Name="FillColorPickerControl" Margin="0,8,0,0" Brush="Red" ColorChanged="FillColorPickerControl_ColorChanged"/>
+                </StackPanel>
+                <StackPanel Height="68" Margin="5">
+                    <TextBlock Text="Line Color" FontWeight="SemiBold" FontSize="14" LineHeight="16"  FontFamily="Segoe UI"/>
+                    <cpdfcommon:ColorPickerControl x:Name="BorderColorPickerControl" Margin="0,8,0,0" Brush="Red" TransparentBtnProperty ="Collapsed" ColorChanged="BorderColorPickerControl_ColorChanged"/>
+                </StackPanel>
+                <StackPanel Height="68" Margin="5">
+                    <TextBlock Text="Opacity" FontWeight="SemiBold" FontSize="14" LineHeight="16"  FontFamily="Segoe UI"/>
+                    <cpdfcommon:CPDFOpacityControl x:Name="CPDFOpacityControl" Margin="0,8,0,0" OpacityChanged="CPDFOpacityControl_OpacityChanged"/>
+                </StackPanel>
+                <StackPanel x:Name="LineStyleStackPanel" Height="90" Margin="5">
+                    <TextBlock Text="Line and Border Style"/>
+                    <cpdfcommon:CPDFLineStyleControl x:Name="CPDFLineStyleControl" Margin="0,8,0,0" LineStyleChanged="CPDFLineStyleControl_LineStyleChanged"/>
+                </StackPanel>
+                <StackPanel x:Name="FontColorStackPanel" Height="75" Margin="5">
+                    <TextBlock Text="Font Color" FontWeight="SemiBold" FontSize="14" LineHeight="16"  FontFamily="Segoe UI"/>
+                    <cpdfcommon:ColorPickerControl x:Name="FontColorPickerControl" TransparentBtnProperty ="Collapsed" Brush="Transparent" Margin="0,8,0,0" ColorChanged="FontColorPickerControl_ColorChanged"/>
+                </StackPanel>
+                <StackPanel>
+                    <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="Text" FontSize="14" FontFamily="Segoe UI" FontWeight="Bold" />
+                    <ComboBox x:Name="FontCombox" Margin="0,8,0,0" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FontCombox_SelectionChanged">
+                        <ComboBoxItem Content="Arial"/>
+                        <ComboBoxItem Content="Courier New"/>
+                        <ComboBoxItem Content="Times New Roman"/>
+                    </ComboBox>
+                    <StackPanel Orientation="Horizontal" >
+                        <ComboBox x:Name="FontStyleCombox"  Margin="0,8,0,0" Width="148" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FontStyleCombox_SelectionChanged">
+                            <ComboBoxItem Content="Regular"/>
+                            <ComboBoxItem Content="Bold"/>
+                            <ComboBoxItem Content="Italic"/>
+                            <ComboBoxItem Content="Bold Italic"/>
+                        </ComboBox>
+                        <ComboBox x:Name="FontSizeComboBox" Margin="4,8,0,0" Width="72" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FontSizeCombox_SelectionChanged"/>
+                    </StackPanel>
+                </StackPanel>
+                <StackPanel Height="160" Margin="5">
+                    <TextBlock Text="Note"></TextBlock>
+                    <TextBox Height="100"  x:Name="NoteTextBox"  TextChanged="NoteTextBox_TextChanged" TextWrapping="Wrap" AcceptsReturn="True"></TextBox>
+                </StackPanel>
+            </StackPanel>
+        </Grid>
+    </ScrollViewer>
+</UserControl>

+ 298 - 0
Demo/Examples/Compdfkit_Tools/Measure/Property/PolygonalProperty.xaml.cs

@@ -0,0 +1,298 @@
+using Compdfkit_Tools.Common;
+using ComPDFKitViewer;
+using ComPDFKitViewer.AnnotEvent;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Compdfkit_Tools.Measure.Property
+{
+    /// <summary>
+    /// PolygonalProperty.xaml 的交互逻辑
+    /// </summary>
+    public partial class PolygonalProperty : UserControl
+    {
+        public ObservableCollection<int> SizeList { get; set; } = new ObservableCollection<int>
+        {
+            6,8,9,10,12,14,18,20,24,26,28,32,30,32,48,72
+        };
+
+        bool IsLoadedData = false;
+
+
+        private AnnotAttribEvent PolygonalEvent { get; set; }
+
+        public PolygonalProperty()
+        {
+            InitializeComponent();
+        }
+
+        private void NoteTextBox_TextChanged(object sender, TextChangedEventArgs e)
+        {
+            if (IsLoadedData)
+            {
+                PolygonalEvent?.UpdateAttrib(AnnotAttrib.NoteText, NoteTextBox.Text);
+                PolygonalEvent?.UpdateAnnot();
+            }
+        }
+
+        private void FontStyleCombox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+            if (IsLoadedData)
+            {
+                int selectIndex = Math.Max(0, FontStyleCombox.SelectedIndex);
+                bool isBold = false;
+                bool isItalic = false;
+
+                switch (selectIndex)
+                {
+                    case 0:
+                        isBold = false;
+                        isItalic = false;
+                        break;
+                    case 1:
+                        isBold = true;
+                        isItalic = false;
+                        break;
+                    case 2:
+                        isBold = false;
+                        isItalic = true;
+                        break;
+                    case 3:
+                        isBold = true;
+                        isItalic = true;
+                        break;
+                    default:
+                        break;
+                }
+                PolygonalEvent?.UpdateAttrib(AnnotAttrib.IsBold, isBold);
+                PolygonalEvent?.UpdateAttrib(AnnotAttrib.IsItalic, isItalic);
+                PolygonalEvent?.UpdateAnnot();
+            }
+        }
+
+        private void FontSizeCombox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+            if (IsLoadedData)
+            {
+                PolygonalEvent?.UpdateAttrib(AnnotAttrib.FontSize, (sender as ComboBox).SelectedItem);
+                PolygonalEvent?.UpdateAnnot();
+            }
+        }
+
+        private void FontCombox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+            ComboBoxItem selectItem = FontCombox.SelectedItem as ComboBoxItem;
+            if (selectItem != null && selectItem.Content != null)
+            {
+                PolygonalEvent?.UpdateAttrib(AnnotAttrib.FontName, selectItem.Content.ToString());
+                PolygonalEvent?.UpdateAnnot();
+            }
+        }
+
+        private void UserControl_Loaded(object sender, RoutedEventArgs e)
+        {
+            Binding SizeListbinding = new Binding();
+            SizeListbinding.Source = this;
+            SizeListbinding.Path = new System.Windows.PropertyPath("SizeList");
+            FontSizeComboBox.SetBinding(ComboBox.ItemsSourceProperty, SizeListbinding);
+            IsLoadedData = true;
+        }
+
+        private void UserControl_Unloaded(object sender, RoutedEventArgs e)
+        {
+            IsLoadedData = false;
+        }
+
+        private void BorderColorPickerControl_ColorChanged(object sender, EventArgs e)
+        {
+            SolidColorBrush checkBrush = BorderColorPickerControl.GetBrush() as SolidColorBrush;
+            if (checkBrush != null)
+            {
+                PolygonalEvent?.UpdateAttrib(AnnotAttrib.Color, checkBrush.Color);
+                PolygonalEvent?.UpdateAnnot();
+            }
+        }
+
+        private void FillColorPickerControl_ColorChanged(object sender, EventArgs e)
+        {
+            SolidColorBrush checkBrush = FillColorPickerControl.GetBrush() as SolidColorBrush;
+            if (checkBrush != null)
+            {
+                PolygonalEvent?.UpdateAttrib(AnnotAttrib.FillColor, checkBrush.Color);
+                PolygonalEvent?.UpdateAnnot();
+            }
+        }
+
+        private void CPDFOpacityControl_OpacityChanged(object sender, EventArgs e)
+        {
+            if (IsLoadedData)
+            {
+                PolygonalEvent?.UpdateAttrib(AnnotAttrib.Transparency, CPDFOpacityControl.OpacityValue / 100D);
+                PolygonalEvent?.UpdateAnnot();
+            }
+        }
+
+        private void CPDFLineStyleControl_LineStyleChanged(object sender, EventArgs e)
+        {
+            if (IsLoadedData)
+            {
+                PolygonalEvent?.UpdateAttrib(AnnotAttrib.LineStyle, CPDFLineStyleControl.DashStyle);
+                PolygonalEvent?.UpdateAnnot();
+            }
+        }
+
+        private void FontColorPickerControl_ColorChanged(object sender, EventArgs e)
+        {
+            SolidColorBrush checkBrush = FontColorPickerControl.GetBrush() as SolidColorBrush;
+            if (checkBrush != null)
+            {
+                PolygonalEvent?.UpdateAttrib(AnnotAttrib.FontColor, checkBrush.Color);
+                PolygonalEvent?.UpdateAnnot();
+            }
+        }
+
+        public void SetAnnotArgsData(PolygonMeasureArgs annotArgs)
+        {
+            Dictionary<AnnotAttrib, object> attribDict = new Dictionary<AnnotAttrib, object>();
+            attribDict[AnnotAttrib.Color] = annotArgs.LineColor;
+            attribDict[AnnotAttrib.Transparency] = annotArgs.Transparency;
+            attribDict[AnnotAttrib.Thickness] = annotArgs.LineWidth;
+            attribDict[AnnotAttrib.LineStyle] = annotArgs.LineDash;
+            attribDict[AnnotAttrib.FontColor] = annotArgs.FontColor;
+            attribDict[AnnotAttrib.FillColor] = annotArgs.FillColor;
+            attribDict[AnnotAttrib.FontName] = annotArgs.FontName;
+            attribDict[AnnotAttrib.IsBold] = annotArgs.IsBold;
+            attribDict[AnnotAttrib.IsItalic] = annotArgs.IsItalic;
+            attribDict[AnnotAttrib.FontSize] = annotArgs.FontSize;
+            attribDict[AnnotAttrib.NoteText] = annotArgs.Content;
+
+            AnnotAttribEvent annotEvent = AnnotAttribEvent.GetAnnotAttribEvent(annotArgs, attribDict);
+            SetAnnotEventData(annotEvent);
+        }
+
+        public void SetAnnotEventData(AnnotAttribEvent annotEvent)
+        {
+            PolygonalEvent = null;
+            if (annotEvent != null)
+            {
+                foreach (AnnotAttrib attrib in annotEvent.Attribs.Keys)
+                {
+                    switch (attrib)
+                    {
+                        case AnnotAttrib.Color:
+                            BorderColorPickerControl.SetCheckedForColor((Color)annotEvent.Attribs[attrib]);
+                            break;
+                        case AnnotAttrib.FillColor:
+                            FillColorPickerControl.SetCheckedForColor((Color)annotEvent.Attribs[attrib]);
+                            break;
+                        case AnnotAttrib.Transparency:
+                            double transparennt = Convert.ToDouble(annotEvent.Attribs[attrib]);
+                            if (transparennt > 1)
+                            {
+                                transparennt = (transparennt / 255D);
+                            }
+                            CPDFOpacityControl.OpacityValue = (int)(transparennt * 100);
+                            break;
+                        case AnnotAttrib.LineStyle:
+                            CPDFLineStyleControl.DashStyle = (DashStyle)(annotEvent.Attribs[attrib]);
+                            break;
+                        case AnnotAttrib.FontColor:
+                            FontColorPickerControl.SetCheckedForColor((Color)annotEvent.Attribs[attrib]);
+                            break;
+                        case AnnotAttrib.FontName:
+                            {
+                                string fontName = (string)annotEvent.Attribs[AnnotAttrib.FontName];
+                                if (fontName.Contains("Courier"))
+                                {
+                                    FontCombox.SelectedIndex = 1;
+                                }
+                                else if (fontName == "Arial" || fontName.Contains("Helvetica"))
+                                {
+                                    FontCombox.SelectedIndex = 0;
+
+                                }
+                                else if (fontName.Contains("Times"))
+                                {
+                                    FontCombox.SelectedIndex = 2;
+                                }
+                                else
+                                {
+                                    FontCombox.SelectedIndex = -1;
+                                }
+                            }
+                            break;
+                        case AnnotAttrib.FontSize:
+                            SetFontSize(Convert.ToDouble(annotEvent.Attribs[attrib]));
+                            break;
+                        case AnnotAttrib.NoteText:
+                            NoteTextBox.Text = annotEvent.Attribs[attrib].ToString();
+                            break;
+                        default:
+                            break;
+                    }
+                }
+
+
+                bool isBold = false;
+                bool isItalic = false;
+                if (annotEvent.Attribs.ContainsKey(AnnotAttrib.IsBold))
+                {
+                    isBold = (bool)annotEvent.Attribs[AnnotAttrib.IsBold];
+                }
+                if (annotEvent.Attribs.ContainsKey(AnnotAttrib.IsItalic))
+                {
+                    isItalic = (bool)annotEvent.Attribs[AnnotAttrib.IsItalic];
+                }
+
+                SetFontStyle(isBold, isItalic);
+            }
+
+            PolygonalEvent = annotEvent;
+        }
+
+        public void SetFontStyle(bool isBold, bool isItalic)
+        {
+            if (isBold == false && isItalic == false)
+            {
+                FontStyleCombox.SelectedIndex = 0;
+                return;
+            }
+
+            if (isBold && isItalic == false)
+            {
+                FontStyleCombox.SelectedIndex = 1;
+                return;
+            }
+
+            if (isBold == false && isItalic)
+            {
+                FontStyleCombox.SelectedIndex = 2;
+                return;
+            }
+
+            if (isBold && isItalic)
+            {
+                FontStyleCombox.SelectedIndex = 3;
+            }
+        }
+
+        private void SetFontSize(double size)
+        {
+            int index = SizeList.IndexOf((int)size);
+            FontSizeComboBox.SelectedIndex = index;
+        }
+    }
+}

+ 87 - 0
Demo/Examples/Compdfkit_Tools/Measure/Property/StraightnessProperty.xaml

@@ -0,0 +1,87 @@
+<UserControl x:Class="Compdfkit_Tools.Measure.Property.StraightnessProperty"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:Compdfkit_Tools.Measure.Property" 
+             xmlns:cpdfcommon="clr-namespace:Compdfkit_Tools.Common" 
+             xmlns:cpdftools="clr-namespace:Compdfkit_Tools.PDFControl"
+             mc:Ignorable="d"
+             Loaded="UserControl_Loaded"
+             Unloaded="UserControl_Unloaded"
+             >
+    <UserControl.Resources>
+        <ResourceDictionary>
+            <ResourceDictionary.MergedDictionaries>
+                <ResourceDictionary Source="../../Asset/Styles/ComboBoxStyle.xaml"></ResourceDictionary>
+            </ResourceDictionary.MergedDictionaries>
+        </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="Appearance"  HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16" FontWeight="Bold" FontFamily="Segoe UI"></TextBlock>
+                    </Grid>
+                </Border>
+                <StackPanel Height="68" Margin="5">
+                    <TextBlock Text="Line Color" FontWeight="SemiBold" FontSize="14" LineHeight="16"  FontFamily="Segoe UI"/>
+                    <cpdfcommon:ColorPickerControl Margin="0,8,0,0" x:Name="BorderColorPickerControl" Brush="Red" TransparentBtnProperty ="Collapsed"
+                                                   ColorChanged="BorderColorPickerControl_ColorChanged"/>
+                </StackPanel>
+                <StackPanel Height="68" Margin="5">
+                    <TextBlock Text="Opacity" FontWeight="SemiBold" FontSize="14" LineHeight="16"  FontFamily="Segoe UI"/>
+                    <cpdfcommon:CPDFOpacityControl Margin="0,8,0,0" x:Name="CPDFOpacityControl" OpacityChanged="CPDFOpacityControl_OpacityChanged">
+                    </cpdfcommon:CPDFOpacityControl>
+                </StackPanel>
+                <StackPanel Height="68" Margin="5">
+                    <TextBlock Text="Line Width" FontWeight="SemiBold" FontSize="14" LineHeight="16"  FontFamily="Segoe UI"></TextBlock>
+                    <cpdfcommon:CPDFThicknessControl Margin="0,8,0,0" x:Name="CPDFThicknessControl" 
+                                                     ThicknessChanged="CPDFThicknessControl_ThicknessChanged">
+                    </cpdfcommon:CPDFThicknessControl>
+                </StackPanel>
+                <StackPanel x:Name="LineStyleStackPanel" Height="90" Margin="5">
+                    <TextBlock Text="Line and Border Style" FontWeight="SemiBold" FontSize="14" LineHeight="16"  FontFamily="Segoe UI"/>
+                    <cpdfcommon:CPDFLineStyleControl Margin="0,8,0,0" x:Name="CPDFLineStyleControl" 
+                                                     LineStyleChanged="CPDFLineStyleControl_LineStyleChanged">
+                    </cpdfcommon:CPDFLineStyleControl>
+                </StackPanel>
+                <StackPanel x:Name="ArrowStackPanel" Visibility="Visible" Height="75"  Margin="5">
+                    <TextBlock Text="Start and End" Margin="0,0,0,10" FontWeight="SemiBold" FontSize="14" LineHeight="16"  FontFamily="Segoe UI"/>
+                    <cpdfcommon:CPDFArrowControl x:Name="CPDFArrowControl" ArrowChanged="CPDFArrowControl_ArrowChanged">
+                    </cpdfcommon:CPDFArrowControl>
+                </StackPanel>
+                <StackPanel x:Name="FontColorStackPanel" Height="75" Margin="5">
+                    <TextBlock Text="Font Color" FontWeight="SemiBold" FontSize="14" LineHeight="16"  FontFamily="Segoe UI"/>
+                    <cpdfcommon:ColorPickerControl Margin="0,8,0,0" x:Name="FontColorPickerControl" Brush="Transparent" TransparentBtnProperty ="Collapsed"
+                                                   ColorChanged="FontColorPickerControl_ColorChanged"></cpdfcommon:ColorPickerControl>
+                </StackPanel>
+                <StackPanel Margin="5">
+                    <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="Text" FontSize="14" FontFamily="Segoe UI" FontWeight="Bold" />
+                    <ComboBox x:Name="FontCombox" Margin="0,8,0,0" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FontCombox_SelectionChanged">
+                        <ComboBoxItem Content="Arial"/>
+                        <ComboBoxItem Content="Courier New"/>
+                        <ComboBoxItem Content="Times New Roman"/>
+                    </ComboBox>
+                    <StackPanel Orientation="Horizontal"  >
+                        <ComboBox x:Name="FontStyleCombox"  Margin="0,8,0,0" Width="148" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FontStyleCombox_SelectionChanged">
+                            <ComboBoxItem Content="Regular"/>
+                            <ComboBoxItem Content="Bold"/>
+                            <ComboBoxItem Content="Italic"/>
+                            <ComboBoxItem Content="Bold Italic"/>
+                        </ComboBox>
+                        <Grid Grid.Row="1" Grid.Column="1" Margin="8,8,0,0">
+                            <ComboBox Name="FontSizeComboBox" Width="72" Height="28" BorderThickness="1" MaxDropDownHeight="200" Foreground="#43474D" FontSize="14"
+                                      SelectionChanged="FontSizeComboBox_SelectionChanged" Style="{StaticResource ComboBoxStyle1}"/>
+                        </Grid>
+                    </StackPanel>
+                </StackPanel>
+                <StackPanel Height="160" Margin="5">
+                    <TextBlock Text="Note"></TextBlock>
+                    <TextBox Height="100"  x:Name="NoteTextBox"  TextChanged="NoteTextBox_TextChanged" TextWrapping="Wrap" AcceptsReturn="True"></TextBox>
+                </StackPanel>
+            </StackPanel>
+        </Grid>
+    </ScrollViewer>
+</UserControl>

+ 308 - 0
Demo/Examples/Compdfkit_Tools/Measure/Property/StraightnessProperty.xaml.cs

@@ -0,0 +1,308 @@
+using ComPDFKit.PDFAnnotation;
+using Compdfkit_Tools.Common;
+using Compdfkit_Tools.Data;
+using ComPDFKitViewer;
+using ComPDFKitViewer.AnnotEvent;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Compdfkit_Tools.Measure.Property
+{
+    /// <summary>
+    /// StraightnessProperty.xaml 的交互逻辑
+    /// </summary>
+    public partial class StraightnessProperty : UserControl
+    {
+        private AnnotAttribEvent LineEvent { get; set; }
+        public ObservableCollection<int> SizeList { get; set; } = new ObservableCollection<int>
+        {
+            6,8,9,10,12,14,18,20,24,26,28,32,30,32,48,72
+        };
+
+        bool IsLoadedData = false;
+
+        public StraightnessProperty()
+        {
+            InitializeComponent();
+        }
+
+        private void NoteTextBox_TextChanged(object sender, TextChangedEventArgs e)
+        {
+            LineEvent?.UpdateAttrib(AnnotAttrib.NoteText, NoteTextBox.Text);
+            LineEvent?.UpdateAnnot();
+        }
+
+        private void FontStyleCombox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+            int selectIndex = Math.Max(0, FontStyleCombox.SelectedIndex);
+            bool isBold = false;
+            bool isItalic = false;
+
+            switch (selectIndex)
+            {
+                case 0:
+                    isBold = false;
+                    isItalic = false;
+                    break;
+                case 1:
+                    isBold = true;
+                    isItalic = false;
+                    break;
+                case 2:
+                    isBold = false;
+                    isItalic = true;
+                    break;
+                case 3:
+                    isBold = true;
+                    isItalic = true;
+                    break;
+                default:
+                    break;
+            }
+            LineEvent?.UpdateAttrib(AnnotAttrib.IsBold, isBold);
+            LineEvent?.UpdateAttrib(AnnotAttrib.IsItalic, isItalic);
+            LineEvent?.UpdateAnnot();
+        }
+
+        private void FontSizeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+            if (IsLoadedData)
+            {
+                LineEvent?.UpdateAttrib(AnnotAttrib.FontSize, (sender as ComboBox).SelectedItem);
+                LineEvent?.UpdateAnnot();
+            }
+        }
+
+        private void FontCombox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+            ComboBoxItem selectItem = FontCombox.SelectedItem as ComboBoxItem;
+            if (selectItem != null && selectItem.Content != null)
+            {
+                LineEvent?.UpdateAttrib(AnnotAttrib.FontName, selectItem.Content.ToString());
+                LineEvent?.UpdateAnnot();
+            }
+        }
+
+        private void BorderColorPickerControl_ColorChanged(object sender, EventArgs e)
+        {
+            SolidColorBrush checkBrush = BorderColorPickerControl.GetBrush() as SolidColorBrush;
+            if (checkBrush != null)
+            {
+                LineEvent?.UpdateAttrib(AnnotAttrib.Color, checkBrush.Color);
+                LineEvent?.UpdateAnnot();
+            }
+        }
+
+        private void CPDFOpacityControl_OpacityChanged(object sender, EventArgs e)
+        {
+            LineEvent?.UpdateAttrib(AnnotAttrib.Transparency, CPDFOpacityControl.OpacityValue/100D);
+            LineEvent?.UpdateAnnot();
+        }
+
+        public void SetAnnotEventData(AnnotAttribEvent annotEvent)
+        {
+            LineEvent = null;
+            if(annotEvent!=null)
+            {
+                foreach(AnnotAttrib attrib in annotEvent.Attribs.Keys)
+                {
+                    switch(attrib)
+                    {
+                        case AnnotAttrib.Color:
+                            BorderColorPickerControl.SetCheckedForColor((Color)annotEvent.Attribs[attrib]);
+                            break;
+                        case AnnotAttrib.Transparency:
+                            double transparennt= Convert.ToDouble(annotEvent.Attribs[attrib]);
+                            if(transparennt>1)
+                            {
+                                transparennt =(transparennt / 255D);
+                            }
+                            CPDFOpacityControl.OpacityValue = (int)(transparennt*100);
+                            break;
+                        case AnnotAttrib.Thickness:
+                            CPDFThicknessControl.Thickness = Convert.ToInt16(annotEvent.Attribs[attrib]);
+                            break;
+                        case AnnotAttrib.LineStyle:
+                            CPDFLineStyleControl.DashStyle= (DashStyle)(annotEvent.Attribs[attrib]);
+                            break;
+                        case AnnotAttrib.FontColor:
+                            FontColorPickerControl.SetCheckedForColor((Color)annotEvent.Attribs[attrib]);
+                            break;
+                        case AnnotAttrib.FontName:
+                            {
+                                string fontName= (string)annotEvent.Attribs[AnnotAttrib.FontName];
+                                if (fontName.Contains("Courier"))
+                                {
+                                    FontCombox.SelectedIndex = 1;
+                                }
+                                else if (fontName == "Arial" || fontName.Contains("Helvetica"))
+                                {
+                                    FontCombox.SelectedIndex = 0;
+
+                                }
+                                else if (fontName.Contains("Times"))
+                                {
+                                    FontCombox.SelectedIndex = 2;
+                                }
+                                else
+                                {
+                                    FontCombox.SelectedIndex = -1;
+                                }
+                            }
+                            break;
+                        case AnnotAttrib.FontSize:
+                            SetFontSize(Convert.ToDouble(annotEvent.Attribs[attrib]));
+                            break;
+                        case AnnotAttrib.NoteText:
+                            NoteTextBox.Text= annotEvent.Attribs[attrib].ToString();
+                            break;
+                        default:
+                            break;
+                    }
+                }
+
+                C_LINE_TYPE headLineType = C_LINE_TYPE.LINETYPE_NONE;
+                C_LINE_TYPE tailLineType = C_LINE_TYPE.LINETYPE_NONE;
+
+                if(annotEvent.Attribs.ContainsKey(AnnotAttrib.LineStart))
+                {
+                    headLineType = (C_LINE_TYPE)annotEvent.Attribs[AnnotAttrib.LineStart];
+                }
+                if (annotEvent.Attribs.ContainsKey(AnnotAttrib.LineEnd))
+                {
+                    tailLineType = (C_LINE_TYPE)annotEvent.Attribs[AnnotAttrib.LineEnd];
+                }
+                LineType lineType = new LineType()
+                {
+                    HeadLineType = headLineType,
+                    TailLineType = tailLineType
+                };
+                CPDFArrowControl.LineType = lineType;
+
+                bool isBold=false; 
+                bool isItalic=false;
+                if (annotEvent.Attribs.ContainsKey(AnnotAttrib.IsBold))
+                {
+                    isBold = (bool)annotEvent.Attribs[AnnotAttrib.IsBold];
+                }
+                if (annotEvent.Attribs.ContainsKey(AnnotAttrib.IsItalic))
+                {
+                    isItalic = (bool)annotEvent.Attribs[AnnotAttrib.IsItalic];
+                }
+
+                SetFontStyle(isBold, isItalic);
+            }
+
+            LineEvent =annotEvent;
+        }
+
+        public void SetAnnotArgsData(LineMeasureArgs annotArgs)
+        {
+            Dictionary<AnnotAttrib, object> attribDict = new Dictionary<AnnotAttrib, object>();
+            attribDict[AnnotAttrib.Color] = annotArgs.LineColor;
+            attribDict[AnnotAttrib.Transparency] = annotArgs.Transparency;
+            attribDict[AnnotAttrib.Thickness] = annotArgs.LineWidth;
+            attribDict[AnnotAttrib.LineStyle] = annotArgs.LineDash;
+            attribDict[AnnotAttrib.LineStart] = annotArgs.HeadLineType;
+            attribDict[AnnotAttrib.LineEnd] = annotArgs.TailLineType;
+            attribDict[AnnotAttrib.FontColor] = annotArgs.FontColor;
+            attribDict[AnnotAttrib.FontName] = annotArgs.FontName;
+            attribDict[AnnotAttrib.IsBold] = annotArgs.IsBold;
+            attribDict[AnnotAttrib.IsItalic] = annotArgs.IsItalic;
+            attribDict[AnnotAttrib.FontSize] = annotArgs.FontSize;
+            attribDict[AnnotAttrib.NoteText] = annotArgs.Content;
+
+            AnnotAttribEvent annotEvent = AnnotAttribEvent.GetAnnotAttribEvent(annotArgs, attribDict);
+            SetAnnotEventData(annotEvent);
+        }
+
+        public void SetFontStyle(bool isBold, bool isItalic)
+        {
+            if (isBold == false && isItalic == false)
+            {
+                FontStyleCombox.SelectedIndex = 0;
+                return;
+            }
+
+            if (isBold && isItalic == false)
+            {
+                FontStyleCombox.SelectedIndex = 1;
+                return;
+            }
+
+            if (isBold == false && isItalic)
+            {
+                FontStyleCombox.SelectedIndex = 2;
+                return;
+            }
+
+            if (isBold && isItalic)
+            {
+                FontStyleCombox.SelectedIndex = 3;
+            }
+        }
+
+        private void SetFontSize(double size)
+        {
+            int index = SizeList.IndexOf((int)size);
+            FontSizeComboBox.SelectedIndex = index;
+        }
+
+        private void CPDFThicknessControl_ThicknessChanged(object sender, EventArgs e)
+        {
+            LineEvent?.UpdateAttrib(AnnotAttrib.Thickness, CPDFThicknessControl.Thickness);
+            LineEvent?.UpdateAnnot();
+        }
+
+        private void CPDFLineStyleControl_LineStyleChanged(object sender, EventArgs e)
+        {
+            LineEvent?.UpdateAttrib(AnnotAttrib.LineStyle, CPDFLineStyleControl.DashStyle);
+            LineEvent?.UpdateAnnot();
+        }
+
+        private void CPDFArrowControl_ArrowChanged(object sender, EventArgs e)
+        {
+            LineEvent?.UpdateAttrib(AnnotAttrib.LineStart, CPDFArrowControl.LineType.HeadLineType);
+            LineEvent?.UpdateAttrib(AnnotAttrib.LineEnd, CPDFArrowControl.LineType.TailLineType);
+            LineEvent?.UpdateAnnot();
+        }
+
+        private void FontColorPickerControl_ColorChanged(object sender, EventArgs e)
+        {
+            SolidColorBrush checkBrush = FontColorPickerControl.GetBrush() as SolidColorBrush;
+            if (checkBrush != null)
+            {
+                LineEvent?.UpdateAttrib(AnnotAttrib.FontColor, checkBrush.Color);
+                LineEvent?.UpdateAnnot();
+            }
+        }
+
+        private void UserControl_Loaded(object sender, RoutedEventArgs e)
+        {
+            Binding SizeListbinding = new Binding();
+            SizeListbinding.Source = this;
+            SizeListbinding.Path = new System.Windows.PropertyPath("SizeList");
+            FontSizeComboBox.SetBinding(ComboBox.ItemsSourceProperty, SizeListbinding);
+            IsLoadedData = true;
+        }
+
+        private void UserControl_Unloaded(object sender, RoutedEventArgs e)
+        {
+            IsLoadedData = false;
+        }
+    }
+}

+ 1 - 1
Demo/Examples/Compdfkit_Tools/PDFView/PDFDisplaySettings/PDFDisplaySettingsUI/CPDFViewModeUI.xaml

@@ -183,7 +183,7 @@
                         <ToggleButton Name="ContinuePageBtn" Style="{StaticResource ToggleButtonSwitchStyle}" Margin="0,0,33,0" Grid.Column="1" Width="40" BorderThickness="0"
                                   Click="ContinuePageBtn_Click"></ToggleButton>
                     </Grid>
-                    <Grid Grid.Row="1" x:Name="CropContainer">
+                    <Grid Grid.Row="1" x:Name="CropContainer" Visibility="Visible">
                         <Grid.ColumnDefinitions>
                             <ColumnDefinition Width="*"></ColumnDefinition>
                             <ColumnDefinition Width="auto"></ColumnDefinition>

+ 0 - 8
Demo/Examples/ContentEditor/ContentEditor.csproj

@@ -106,14 +106,6 @@
     <None Include="App.config" />
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="..\..\..\..\compdfkit\ComPDFKit\ComPDFKitCSharp\ComPDFKit.Desk.csproj">
-      <Project>{56e518ad-c126-4b48-9a09-0a64c87020e4}</Project>
-      <Name>ComPDFKit.Desk</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\..\..\compdfkit\ComPDFKit\ComPDFKitDesktop\ComPDFKit.Viewer\ComPDFKit.Viewer.csproj">
-      <Project>{18ec356d-8130-49d4-b4e6-ac290e1065b7}</Project>
-      <Name>ComPDFKit.Viewer</Name>
-    </ProjectReference>
     <ProjectReference Include="..\Compdfkit_Tools\Compdfkit_Tools.csproj">
       <Project>{9363bcb1-3a67-446a-8093-5708b86bf418}</Project>
       <Name>Compdfkit_Tools</Name>

+ 16 - 2
Demo/Examples/Examlpes.sln

@@ -114,9 +114,11 @@ Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BookmarkTest", "Samples\Boo
 EndProject
 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "DigitalSignatureTest", "Samples\DigitalSignatureTest\VB\DigitalSignatureTest.vbproj", "{84A958E6-C1DA-42C4-88E5-EBF4E3E632FE}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComPDFKit.Desk", "..\..\..\compdfkit\ComPDFKit\ComPDFKitCSharp\ComPDFKit.Desk.csproj", "{56E518AD-C126-4B48-9A09-0A64C87020E4}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Measure", "Measure\Measure.csproj", "{75A0C673-E1D8-4FCE-8804-95E4F0630200}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComPDFKit.Viewer", "..\..\..\compdfkit\ComPDFKit\ComPDFKitDesktop\ComPDFKit.Viewer\ComPDFKit.Viewer.csproj", "{18EC356D-8130-49D4-B4E6-AC290E1065B7}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComPDFKit.Desk", "..\..\..\compdfkit_windows\ComPDFKit\ComPDFKitCSharp\ComPDFKit.Desk.csproj", "{56E518AD-C126-4B48-9A09-0A64C87020E4}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComPDFKit.Viewer", "..\..\..\compdfkit_windows\ComPDFKit\ComPDFKitDesktop\ComPDFKit.Viewer\ComPDFKit.Viewer.csproj", "{18EC356D-8130-49D4-B4E6-AC290E1065B7}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -726,6 +728,18 @@ Global
 		{84A958E6-C1DA-42C4-88E5-EBF4E3E632FE}.Release|x64.Build.0 = Release|Any CPU
 		{84A958E6-C1DA-42C4-88E5-EBF4E3E632FE}.Release|x86.ActiveCfg = Release|Any CPU
 		{84A958E6-C1DA-42C4-88E5-EBF4E3E632FE}.Release|x86.Build.0 = Release|Any CPU
+		{75A0C673-E1D8-4FCE-8804-95E4F0630200}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{75A0C673-E1D8-4FCE-8804-95E4F0630200}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{75A0C673-E1D8-4FCE-8804-95E4F0630200}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{75A0C673-E1D8-4FCE-8804-95E4F0630200}.Debug|x64.Build.0 = Debug|Any CPU
+		{75A0C673-E1D8-4FCE-8804-95E4F0630200}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{75A0C673-E1D8-4FCE-8804-95E4F0630200}.Debug|x86.Build.0 = Debug|Any CPU
+		{75A0C673-E1D8-4FCE-8804-95E4F0630200}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{75A0C673-E1D8-4FCE-8804-95E4F0630200}.Release|Any CPU.Build.0 = Release|Any CPU
+		{75A0C673-E1D8-4FCE-8804-95E4F0630200}.Release|x64.ActiveCfg = Release|Any CPU
+		{75A0C673-E1D8-4FCE-8804-95E4F0630200}.Release|x64.Build.0 = Release|Any CPU
+		{75A0C673-E1D8-4FCE-8804-95E4F0630200}.Release|x86.ActiveCfg = Release|Any CPU
+		{75A0C673-E1D8-4FCE-8804-95E4F0630200}.Release|x86.Build.0 = Release|Any CPU
 		{56E518AD-C126-4B48-9A09-0A64C87020E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{56E518AD-C126-4B48-9A09-0A64C87020E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{56E518AD-C126-4B48-9A09-0A64C87020E4}.Debug|x64.ActiveCfg = Debug|x64

+ 8 - 0
Demo/Examples/Forms/Forms.csproj

@@ -98,6 +98,14 @@
     <None Include="packages.config" />
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\..\..\compdfkit_windows\ComPDFKit\ComPDFKitCSharp\ComPDFKit.Desk.csproj">
+      <Project>{56e518ad-c126-4b48-9a09-0a64c87020e4}</Project>
+      <Name>ComPDFKit.Desk</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\compdfkit_windows\ComPDFKit\ComPDFKitDesktop\ComPDFKit.Viewer\ComPDFKit.Viewer.csproj">
+      <Project>{18ec356d-8130-49d4-b4e6-ac290e1065b7}</Project>
+      <Name>ComPDFKit.Viewer</Name>
+    </ProjectReference>
     <ProjectReference Include="..\Compdfkit_Tools\Compdfkit_Tools.csproj">
       <Project>{9363bcb1-3a67-446a-8093-5708b86bf418}</Project>
       <Name>Compdfkit_Tools</Name>

+ 6 - 0
Demo/Examples/Measure/App.config

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+    <startup> 
+        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
+    </startup>
+</configuration>

+ 9 - 0
Demo/Examples/Measure/App.xaml

@@ -0,0 +1,9 @@
+<Application x:Class="Measure.App"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:local="clr-namespace:Measure"
+             StartupUri="MainWindow.xaml">
+    <Application.Resources>
+         
+    </Application.Resources>
+</Application>

+ 34 - 0
Demo/Examples/Measure/App.xaml.cs

@@ -0,0 +1,34 @@
+using ComPDFKit.NativeMethod;
+using Compdfkit_Tools.Helper;
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+using static ComPDFKit.NativeMethod.CPDFSDKVerifier;
+
+namespace Measure
+{
+    /// <summary>
+    /// App.xaml 的交互逻辑
+    /// </summary>
+    public partial class App : Application
+    {
+        protected override void OnStartup(StartupEventArgs e)
+        {
+            base.OnStartup(e);
+            LicenseVerify();
+        }
+
+        private static bool LicenseVerify()
+        {
+            if (!CPDFSDKVerifier.LoadNativeLibrary())
+                return false;
+
+            LicenseErrorCode verifyResult = CPDFSDKVerifier.LicenseVerify(SDKLicenseHelper.ParseLicenseXML(), false);
+            return (verifyResult == LicenseErrorCode.E_LICENSE_SUCCESS);
+        }
+    }
+}

二进制
Demo/Examples/Measure/ComPDFKit_Logo.ico


+ 314 - 0
Demo/Examples/Measure/MainWindow.xaml

@@ -0,0 +1,314 @@
+<Window x:Class="Measure.MainWindow"
+        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:Measure"
+               xmlns:cpdftools="clr-namespace:Compdfkit_Tools.PDFControl;assembly=Compdfkit_Tools"
+        xmlns:cpdfcommon="clr-namespace:Compdfkit_Tools.Common;assembly=Compdfkit_Tools"
+        mc:Ignorable="d"
+        Title="Measure_ComPDFKit V1.10.1" Height="720" Width="1080"  WindowStartupLocation="CenterScreen">
+    <Window.Resources>
+        <ResourceDictionary>
+            <ResourceDictionary.MergedDictionaries>
+                <ResourceDictionary Source="pack://application:,,,/Compdfkit_Tools;component/Asset/Styles/ToggleButtonStyle.xaml"></ResourceDictionary>
+                <ResourceDictionary Source="pack://application:,,,/Compdfkit_Tools;component/Asset/Styles/ButtonStyle.xaml"></ResourceDictionary>
+            </ResourceDictionary.MergedDictionaries>
+
+            <RoutedUICommand x:Key="Open" Text="Open"/>
+            <RoutedUICommand x:Key="Save" Text="Right rotate"/>
+            <RoutedUICommand x:Key="SaveAs" Text="Delete"/>
+            <RoutedUICommand x:Key="Undo" Text="Undo"/>
+            <RoutedUICommand x:Key="Redo" Text="Redo"/>
+            <RoutedUICommand x:Key="ControlLeftPanel" Text="Control left panel"/>
+            <RoutedUICommand x:Key="ControlRightPanel" Text="Control right panel"/>
+            <RoutedUICommand x:Key="GoToBookmark" Text="Go to bookmark"></RoutedUICommand>
+            <RoutedUICommand x:Key="GoToOutline" Text="Go to outline"></RoutedUICommand>
+            <RoutedUICommand x:Key="GoToThumbnail" Text="Go to thumbnail"></RoutedUICommand>
+            <RoutedUICommand x:Key="GoToAnnotationList" Text="Go to annotation list"></RoutedUICommand>
+            <RoutedUICommand x:Key="GoToSearch" Text="Go to search"></RoutedUICommand>
+            <RoutedUICommand x:Key="ScaleAdd" Text="Scale add"></RoutedUICommand>
+            <RoutedUICommand x:Key="ScaleSubtract" Text="Scale reduce"></RoutedUICommand>
+            <RoutedUICommand x:Key="DisplaySettings" Text="Display settings"></RoutedUICommand>
+            <RoutedUICommand x:Key="DocumentInfo" Text="Document infomation"></RoutedUICommand>
+        </ResourceDictionary>
+    </Window.Resources>
+
+
+    <Window.CommandBindings>
+        <CommandBinding Command="{StaticResource Open}" Executed="CommandBinding_Executed_Open"/>
+        <CommandBinding Command="{StaticResource Save}" Executed="CommandBinding_Executed_Save"/>
+        <CommandBinding Command="{StaticResource SaveAs}" Executed="CommandBinding_Executed_SaveAs"/>
+        <CommandBinding Command="{StaticResource ControlLeftPanel}" Executed="CommandBinding_Executed_ControlLeftPanel"></CommandBinding>
+        <CommandBinding Command="{StaticResource GoToBookmark}" Executed="CommandBinding_Executed_Bookmark"></CommandBinding>
+        <CommandBinding Command="{StaticResource GoToOutline}" Executed="CommandBinding_Executed_Outline"></CommandBinding>
+        <CommandBinding Command="{StaticResource GoToThumbnail}" Executed="CommandBinding_Executed_Thumbnail"></CommandBinding>
+        <CommandBinding Command="{StaticResource GoToSearch}" Executed="CommandBinding_Executed_Search"></CommandBinding>
+        <CommandBinding Command="{StaticResource ScaleAdd}" Executed="CommandBinding_Executed_ScaleAdd"></CommandBinding>
+        <CommandBinding Command="{StaticResource ScaleSubtract}" Executed="CommandBinding_Executed_ScaleSubtract"></CommandBinding>
+        <CommandBinding Command="{StaticResource DisplaySettings}" Executed="CommandBinding_Executed_DisplaySettings"></CommandBinding>
+        <CommandBinding Command="{StaticResource DocumentInfo}" Executed="CommandBinding_Executed_DocumentInfo"></CommandBinding>
+    </Window.CommandBindings>
+
+    <Window.InputBindings>
+        <KeyBinding Key="O" Modifiers="Control" Command="{StaticResource Open}"/>
+        <KeyBinding Key="S" Modifiers="Control" Command="{StaticResource Save}"/>
+        <KeyBinding Key="S" Modifiers="Control+Shift" Command="{StaticResource SaveAs}"/>
+        <KeyBinding Key="Z" Modifiers="Control" Command="{StaticResource Undo}"/>
+        <KeyBinding Key="Y" Modifiers="Control" Command="{StaticResource Redo}"/>
+        <KeyBinding Key="F4" Command="{StaticResource ControlLeftPanel}"/>
+        <KeyBinding Key="F4" Modifiers="Control" Command="{StaticResource ControlRightPanel}"/>
+        <KeyBinding Key="B" Modifiers="Control" Command="{StaticResource GoToBookmark}"></KeyBinding>
+        <KeyBinding Key="O" Modifiers="Control+Shift" Command="{StaticResource GoToOutline}"></KeyBinding>
+        <KeyBinding Key="T" Modifiers="Control" Command="{StaticResource GoToThumbnail}"></KeyBinding>
+        <KeyBinding Key="A" Modifiers="Control" Command="{StaticResource GoToAnnotationList}"></KeyBinding>
+        <KeyBinding Key="F" Modifiers="Control" Command="{StaticResource GoToSearch}"></KeyBinding>
+        <KeyBinding Key="Add" Modifiers="Control" Command="{StaticResource ScaleAdd}"></KeyBinding>
+        <KeyBinding Key="Subtract" Modifiers="Control" Command="{StaticResource ScaleSubtract}"></KeyBinding>
+        <KeyBinding Key="D" Modifiers="Control" Command="{StaticResource DisplaySettings}"></KeyBinding>
+        <KeyBinding Key="I" Modifiers="Control" Command="{StaticResource DocumentInfo}"></KeyBinding>
+    </Window.InputBindings>
+
+    <Grid>
+        <Grid>
+            <Grid.RowDefinitions>
+                <RowDefinition Height="40"></RowDefinition>
+                <RowDefinition Height="*"></RowDefinition>
+            </Grid.RowDefinitions>
+            <Border Height="1" Background="LightGray" VerticalAlignment="Bottom"/>
+            <Grid>
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition Width="auto"></ColumnDefinition>
+                    <ColumnDefinition Width="*"></ColumnDefinition>
+                    <ColumnDefinition Width="auto"></ColumnDefinition>
+                </Grid.ColumnDefinitions>
+
+                <StackPanel Orientation="Horizontal" Height="40" Margin="20,0,0,0">
+                    <Button BorderThickness="0" VerticalContentAlignment="Center" Width="30" Height="30" Style="{StaticResource LightButtonStyle}" Background="Transparent" Click="OpenFile_Click">
+                        <Button.Content>
+                            <Viewbox Width="20" Height="20">
+                                <Path Fill="#43474D" >
+                                    <Path.Data>
+                                        M3.75,2 L3.91967773,2.00463867 C4.08325195,2.01391602 4.22851562,2.03710938 4.35546875,2.07421875 C4.52473958,2.12369792 
+                                    4.67578125,2.18489583 4.80859375,2.2578125 C4.94140625,2.33072917 5.05989583,2.41145833 5.1640625,2.5 C5.26822917,2.58854167 
+                                    5.37369792,2.66927083 5.48046875,2.7421875 C5.58723958,2.81510417 5.70182292,2.87630208 5.82421875,2.92578125 C5.94661458,2.97526042 
+                                    6.08854167,3 6.25,3 L6.25,3 L12,3 L12.1371528,3.00868056 C12.2262731,3.02025463 12.3107639,3.04340278 12.390625,3.078125 
+                                    C12.5104167,3.13020833 12.6158854,3.20182292 12.7070312,3.29296875 C12.7981771,3.38411458 12.8697917,3.48958333 12.921875,3.609375 
+                                    C12.9739583,3.72916667 13,3.859375 13,4 L13,4 L13,6 L15,6 L15.1332465,6.00868056 C15.2206308,6.02025463 15.3051215,6.04340278 
+                                    15.3867188,6.078125 C15.5091146,6.13020833 15.6158854,6.20182292 15.7070312,6.29296875 C15.7981771,6.38411458 15.8697917,6.48958333 
+                                    15.921875,6.609375 C15.9739583,6.72916667 16,6.85677083 16,6.9921875 C16,7.1484375 15.9635417,7.29947917 15.890625,7.4453125 
+                                    L15.890625,7.4453125 L12.6171875,14 L0,14 L0,3 L0.00868055556,2.86284722 C0.0202546296,2.77372685 0.0434027778,2.68923611 0.078125,2.609375 
+                                    C0.130208333,2.48958333 0.201822917,2.38411458 0.29296875,2.29296875 C0.384114583,2.20182292 0.489583333,2.13020833 0.609375,2.078125 
+                                    C0.729166667,2.02604167 0.859375,2 1,2 L1,2 L3.75,2 Z M15,7 L4.3125,7 L1.3125,13 L12,13 L15,7 Z M3.75,3 L1,3 L1,11.3828125 L3.4140625,6.5546875 
+                                    L3.48706055,6.43261719 C3.56665039,6.31738281 3.66601562,6.22265625 3.78515625,6.1484375 C3.94401042,6.04947917 4.11979167,6 4.3125,6 
+                                    L4.3125,6 L12,6 L12,4 L6.25,4 L6.08032227,3.99536133 C5.91674805,3.98608398 5.77148438,3.96289062 5.64453125,3.92578125 C5.47526042,3.87630208 
+                                    5.32421875,3.81510417 5.19140625,3.7421875 C5.05859375,3.66927083 4.94010417,3.58854167 4.8359375,3.5 C4.73177083,3.41145833 4.62630208,3.33072917 
+                                    4.51953125,3.2578125 C4.41276042,3.18489583 4.29817708,3.12369792 4.17578125,3.07421875 C4.05338542,3.02473958 3.91145833,3 3.75,3 L3.75,3 Z
+                                    </Path.Data>
+                                </Path>
+                            </Viewbox>
+                        </Button.Content>
+                        <Button.ToolTip>
+                            <ToolTip Content="Open..."></ToolTip>
+                        </Button.ToolTip>
+                    </Button>
+
+                    <Button BorderThickness="0" VerticalContentAlignment="Center" Margin="10,0,0,0" Width="30" Height="30" Style="{StaticResource LightButtonStyle}" Background="Transparent" 
+                            Click="SaveFileBtn_Click"  IsEnabled="{Binding CanSave,Mode=OneWay}">
+                        <Button.Content>
+                            <Viewbox Width="20" Height="20">
+                                <Path Fill="#43474D" >
+                                    <Path.Data>
+                                        M11.707107,1 L15,4.29289322 L15,15 L1,15 L1,1 L11.707107,1 Z M11.293,2 L2,2 L2,14 L4,14 L4,8 L12,8 L12,14 L14,14 L14,4.707 L11.293,2 Z 
+                                        M11,9 L5,9 L5,14 L11,14 L11,9 Z M7,5 L7,6 L4,6 L4,5 L7,5 Z
+                                    </Path.Data>
+                                </Path>
+                            </Viewbox>
+                        </Button.Content>
+                        <Button.ToolTip>
+                            <ToolTip Content="Save"></ToolTip>
+                        </Button.ToolTip>
+                    </Button>
+                    <ToggleButton Name="LeftToolPanelButton" Margin="13,0,0,0" BorderThickness="0" Width="30" Height="30" Style="{StaticResource ToggleButtonStyle}" Background="Transparent" Click="LeftToolPanelButton_Click">
+                        <ToggleButton.Content>
+                            <Path Fill="#43474D" Width="30" Height="30">
+                                <Path.Data>
+                                    M22.5 8.5H7.5V12.25H13H22.5V8.5ZM12.25 13.75H7.5V21.5H12.25V13.75ZM13.75 21.5V13.75H22.5V21.5H13.75ZM7.5 7H6V8.5V21.5V23H7.5H22.5H24V21.5V8.5V7H22.5H7.5Z
+                                </Path.Data>
+                            </Path>
+                        </ToggleButton.Content>
+                        <ToggleButton.ToolTip>
+                            <ToolTip Content="Panel"></ToolTip>
+                        </ToggleButton.ToolTip>
+                    </ToggleButton>
+
+                    <Line Margin="13,0,13,0" Stroke="#E0E0E0" X1="0" Y1="5" X2="0" Y2="35"></Line>
+
+                    <ToggleButton BorderThickness="0" Width="30" Height="30" Style="{StaticResource ToggleButtonStyle}" Background="Transparent" IsChecked="True" IsEnabled="False" Visibility="Collapsed">
+                        <ToggleButton.Content>
+                            <Path Fill="#43474D">
+                                <Path.Data>
+                                    M8.7463 7.94055L8.43134 3.20358C8.38986 2.6073 8.82031 2.08322 9.40947 2.01273L9.46546 2.00656C9.75502 1.97416 10.0451 2.06271 10.2681 2.25159C10.4911 
+                                2.44047 10.6276 2.71317 10.6457 3.00614L10.9886 8.17061C10.999 8.31659 11.1097 8.43516 11.2537 8.45444C11.3176 8.46288 11.382 8.44409 11.4315 
+                                8.40258C11.481 8.36108 11.5111 8.30063 11.5145 8.23584L11.7612 3.47595C11.7918 2.85998 12.3116 2.38523 12.923 2.41468H12.9309C13.5429 2.44972 
+                                14.0111 2.97745 13.9773 3.59407L13.7218 8.51438C13.7137 8.66679 13.8235 8.79975 13.9738 8.81936C14.1225 8.83876 14.2625 8.73915 14.2914 
+                                8.59018L14.8006 6.02337C14.9178 5.41517 15.497 5.01851 16.0954 5.13574L16.1041 5.13751C16.7058 5.25854 17.0969 5.84695 16.979 6.45353L16.3684 
+                                9.53687C15.8189 13.3474 15.0586 15.5052 14.3946 16.4246C13.3649 17.8508 11.5573 17.8667 10.1251 17.8667C8.69381 17.8667 7.16012 17.5291 6.44796 
+                                16.9993C5.73492 16.4696 4.77079 15.2575 4.15837 13.9327L4.16712 13.9283C4.11876 13.8639 4.0774 13.7945 4.04376 13.7212L3.105 11.685C2.84552 11.1243 
+                                3.08338 10.4577 3.63781 10.1918L3.64656 10.1874C3.91235 10.0626 4.21656 10.0497 4.49179 10.1517C4.76702 10.2536 4.99055 10.4619 5.11287 10.7304C5.62206 
+                                11.8234 5.94227 12.324 6.07526 12.2324C6.27386 12.0949 6.12075 11.7176 5.85478 9.21249C5.67578 7.53039 5.45319 5.85328 5.18724 4.18289C5.07653 3.5968 
+                                5.44002 3.02581 6.01489 2.88273L6.07526 2.86775C6.35866 2.79957 6.65742 2.85178 6.90147 3.01215C7.14552 3.17252 7.3134 3.42693 7.36572 3.71571L8.168 
+                                8.02341C8.19642 8.17613 8.33897 8.27937 8.49171 8.25787C8.64561 8.23564 8.75656 8.09774 8.7463 7.94143V7.94055Z
+                                </Path.Data>
+                            </Path>
+                        </ToggleButton.Content>
+                    </ToggleButton>
+
+                    <Line Margin="13,0,13,0" Stroke="#E0E0E0" X1="0" Y1="5" X2="0" Y2="35"></Line>
+                    <cpdftools:CPDFScalingControl x:Name="CPDFSaclingControl"></cpdftools:CPDFScalingControl>
+                </StackPanel>
+
+                <ComboBox Name="ViewModeBox" Width="120" Height="26" Grid.Column="1" HorizontalAlignment="Center" FontSize="14" Foreground="#001A4E" SelectionChanged="ComboBox_SelectionChanged">
+                    <ComboBoxItem>Viewer</ComboBoxItem>
+                    <ComboBoxItem IsSelected="True">Measurement</ComboBoxItem>
+                </ComboBox>
+
+                <StackPanel Orientation="Horizontal" Grid.Column="2">
+
+                    <Button BorderThickness="0" Width="40" Height="40" Style="{StaticResource LightButtonStyle}" Background="Transparent" Click="ExpandSearchBtn_Click">
+                        <Button.Content>
+                            <Path Fill="#43474D">
+                                <Path.Data>
+                                    M5.10992 13.9353C2.71184 11.5372 2.71184 7.64917 5.10992 5.25108C7.50801 2.853 11.3961 2.853 13.7942 5.25108C16.1922 7.64917 
+                                16.1922 11.5372 13.7942 13.9353C11.3961 16.3334 7.50801 16.3334 5.10992 13.9353ZM4.04926 4.19042C1.06539 7.17429 1.06539 12.0121 
+                                4.04926 14.996C6.85422 17.8009 11.2975 17.9691 14.2989 15.5005L17.1989 18.4006C17.4918 18.6935 17.9667 18.6935 18.2596 
+                                18.4006C18.5525 18.1077 18.5525 17.6328 18.2596 17.3399L15.3595 14.4399C17.828 11.4384 17.6597 6.99533 14.8548 
+                                4.19042C11.8709 1.20655 7.03313 1.20655 4.04926 4.19042Z
+                                </Path.Data>
+                            </Path>
+                        </Button.Content>
+                        <Button.ToolTip>
+                            <ToolTip Content="Search"></ToolTip>
+                        </Button.ToolTip>
+                    </Button>
+                 
+                    <ToggleButton  x:Name="RightPanelButton" BorderThickness="0" Width="40" Height="40" Style="{StaticResource ToggleButtonStyle}" Background="Transparent" Click="RightPanelButton_Click">
+                        <ToggleButton.Content>
+                            <Path Fill="#43474D" Width="30" Height="30">
+                                <Path.Data>
+                                    M22.5 8.5H7.5V12.25H13H22.5V8.5ZM12.25 13.75H7.5V21.5H12.25V13.75ZM13.75 21.5V13.75H22.5V21.5H13.75ZM7.5 7H6V8.5V21.5V23H7.5H22.5H24V21.5V8.5V7H22.5H7.5Z
+                                </Path.Data>
+                            </Path>
+                        </ToggleButton.Content>
+                        <ToggleButton.ToolTip>
+                            <ToolTip Content="Properties"></ToolTip>
+                        </ToggleButton.ToolTip>
+                    </ToggleButton>
+                    
+                    <ToggleButton Name="ViewSettingBtn" BorderThickness="0" Width="40" Height="40" Style="{StaticResource ToggleButtonStyle}" Background="Transparent" Click="ViewSettingBtn_Click">
+                        <ToggleButton.Content>
+                            <Path Stroke="#43474D" VerticalAlignment="Center" StrokeThickness="2">
+                                <Path.Data>
+                                    <CombinedGeometry GeometryCombineMode="Exclude">
+                                        <CombinedGeometry.Geometry1>
+                                            M18.3327 10C18.3327 10 14.6017 16.25 9.99935 16.25C5.39698 16.25 1.66602 10 1.66602 10C1.66602 10 5.39698 3.75 9.99935 3.75C14.6017 3.75 18.3327 10 18.3327 10Z
+                                        </CombinedGeometry.Geometry1>
+                                        <CombinedGeometry.Geometry2>
+                                            <EllipseGeometry Center="10,10" RadiusX="2" RadiusY="2"/>
+                                        </CombinedGeometry.Geometry2>
+                                    </CombinedGeometry>
+                                </Path.Data>
+                            </Path>
+                        </ToggleButton.Content>
+                        <ToggleButton.ToolTip>
+                            <ToolTip Content="Page Display"></ToolTip>
+                        </ToggleButton.ToolTip>
+                    </ToggleButton>
+
+                    <Button BorderThickness="0" Width="40" Height="40" Style="{StaticResource LightButtonStyle}" Background="Transparent" Click="PageInfoBtn_Click">
+                        <Button.Content>
+                            <Path Fill="#43474D" VerticalAlignment="Center">
+                                <Path.Data>
+                                    M2.75 10C2.75 5.99594 5.99594 2.75 10 2.75C14.0041 2.75 17.25 5.99594 17.25 10C17.25 14.0041 14.0041 17.25 10 
+                                17.25C5.99594 17.25 2.75 14.0041 2.75 10ZM10 1.25C5.16751 1.25 1.25 5.16751 1.25 10C1.25 14.8325 5.16751 
+                                18.75 10 18.75C14.8325 18.75 18.75 14.8325 18.75 10C18.75 5.16751 14.8325 1.25 10 1.25ZM6.5 11C7.05228 11 
+                                7.5 10.5523 7.5 10C7.5 9.44771 7.05228 9 6.5 9C5.94772 9 5.5 9.44771 5.5 10C5.5 10.5523 5.94772 11 6.5 11ZM10 
+                                11C10.5523 11 11 10.5523 11 10C11 9.44771 10.5523 9 10 9C9.44771 9 9 9.44771 9 10C9 10.5523 9.44771 11 10 11ZM14.5 
+                                10C14.5 10.5523 14.0523 11 13.5 11C12.9477 11 12.5 10.5523 12.5 10C12.5 9.44771 12.9477 9 13.5 9C14.0523 9 14.5 9.44771 14.5 10Z
+                                </Path.Data>
+                            </Path>
+                        </Button.Content>
+                        <Button.ToolTip>
+                            <ToolTip Content="Document Info"></ToolTip>
+                        </Button.ToolTip>
+                    </Button>
+                </StackPanel>
+            </Grid>
+            <Grid Name="BodyGrid" Grid.Row="1">
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition Width="0"></ColumnDefinition>
+                    <ColumnDefinition Width="0"></ColumnDefinition>
+                    <ColumnDefinition Width="*"></ColumnDefinition>
+                    <ColumnDefinition Width="auto"></ColumnDefinition>
+                </Grid.ColumnDefinitions>
+
+                <cpdftools:CPDFBOTABarControl Visibility="Collapsed" Name="BotaSideTool"/>
+
+                <GridSplitter Name="Splitter" Grid.Column="1" Width="15" ResizeBehavior="PreviousAndNext" Visibility="Collapsed">
+                    <GridSplitter.Template>
+                        <ControlTemplate TargetType="{x:Type GridSplitter}">
+                            <Border BorderThickness="{TemplateBinding Border.BorderThickness}"
+                        BorderBrush="{TemplateBinding Border.BorderBrush}"
+                        Background="{TemplateBinding Panel.Background}" >
+                                <Path Fill="Gray" VerticalAlignment="Center">
+                                    <Path.Data>
+                                        M15 3.75H1V2.25H15V3.75ZM15 8.75H1V7.25H15V8.75ZM1 13.75H15V12.25H1V13.75Z
+                                    </Path.Data>
+                                </Path>
+                            </Border>
+                        </ControlTemplate>
+                    </GridSplitter.Template>
+                </GridSplitter>
+
+                <Grid Grid.Column="2" >
+                    <Border x:Name="PDFGrid" Background="#CECECE"></Border>
+
+                    <cpdfcommon:PageNumberControl Name="FloatPageTool" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,20"></cpdfcommon:PageNumberControl>
+                </Grid>
+
+                <Border Name="PropertyContainer" Grid.Column="3" Visibility="Hidden"></Border>
+            </Grid>
+        </Grid>
+
+        <Border Name="PopupBorder" Background="#A0000000" Visibility="Collapsed">
+            <Grid>
+
+                <Grid Name="FileInfoUI"  Width="422" Height="680" HorizontalAlignment="Center" VerticalAlignment="Center" Background="White" Visibility="Collapsed">
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="*"></ColumnDefinition>
+                        <ColumnDefinition Width="*"></ColumnDefinition>
+                    </Grid.ColumnDefinitions>
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="auto"></RowDefinition>
+                        <RowDefinition Height="*"></RowDefinition>
+                    </Grid.RowDefinitions>
+
+                    <TextBlock Height="20" FontSize="14" LineHeight="16" Margin="12,6,0,0" HorizontalAlignment="Left">Document Info:</TextBlock>
+                    <Button Grid.Column="1" Width="16" Height="16" HorizontalAlignment="Right" Margin="0,8,8,0" BorderThickness="0" Click="FileInfoCloseBtn_Click">
+                        <Button.Content>
+                            <Path Fill="Black">
+                                <Path.Data>
+                                    M6.69495 6L11.5 1.19495L10.805 0.5L6 5.30505L1.19495 0.5L0.5 1.19495L5.30505 6L0.5 10.805L1.19495 11.5L6 6.69495L10.805 11.5L11.5 10.805L6.69495 6Z
+                                </Path.Data>
+                            </Path>
+                        </Button.Content>
+                    </Button>
+                    <cpdftools:CPDFInfoControl Grid.Row="1" Margin="25,10,25,0" Grid.ColumnSpan="2" Name="FileInfoControl"></cpdftools:CPDFInfoControl>
+                </Grid>
+
+                <cpdfcommon:PasswordDialog x:Name="PasswordUI" Visibility="Collapsed"></cpdfcommon:PasswordDialog>
+            </Grid>
+
+        </Border>
+    </Grid>
+</Window>

+ 892 - 0
Demo/Examples/Measure/MainWindow.xaml.cs

@@ -0,0 +1,892 @@
+using ComPDFKit.PDFDocument;
+using Compdfkit_Tools.Helper;
+using Compdfkit_Tools.PDFControl;
+using ComPDFKitViewer.AnnotEvent;
+using ComPDFKitViewer.PdfViewer;
+using ComPDFKitViewer;
+using Microsoft.Win32;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+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 System.Drawing;
+using Path = System.IO.Path;
+using Compdfkit_Tools.Measure;
+using static Compdfkit_Tools.Helper.PanelState;
+
+namespace Measure
+{
+    /// <summary>
+    /// MainWindow.xaml 的交互逻辑
+    /// </summary>
+    public partial class MainWindow : Window, INotifyPropertyChanged
+    {
+        #region Property
+        private PDFViewControl passwordViewer;
+        private PDFViewControl pdfViewControl;
+
+        private MeasureControl measureControl = new MeasureControl();
+        CPDFDisplaySettingsControl displayPanel = new CPDFDisplaySettingsControl();
+
+        private int[] zoomLevelList = { 10, 25, 50, 100, 150, 200, 300, 400, 500, 1000 };
+
+        public event PropertyChangedEventHandler PropertyChanged;
+
+        private PanelState panelState = PanelState.GetInstance();
+
+        public bool CanSave
+        {
+            get
+            {
+                if (pdfViewControl != null && pdfViewControl.PDFView != null)
+                {
+                    return pdfViewControl.PDFView.UndoManager.CanSave;
+                }
+                return false;
+            }
+        }
+        #endregion
+
+        public MainWindow()
+        {
+            InitializeComponent();
+            Loaded += MainWindow_Loaded;
+            DataContext = this;
+        }
+
+        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
+        {
+            BotaSideTool.AddBOTAContent(BOTATools.Thumbnail | BOTATools.Outline | BOTATools.Bookmark | BOTATools.Search|BOTATools.Annotation);
+            LoadDefaultDocument();
+            panelState.PropertyChanged -= PanelState_PropertyChanged;
+            panelState.PropertyChanged += PanelState_PropertyChanged;
+        }
+
+        private void PanelState_PropertyChanged(object sender, PropertyChangedEventArgs e)
+        {
+            if (e.PropertyName == nameof(PanelState.RightPanel))
+            {
+                if (panelState.RightPanel == PanelState.RightPanelState.PropertyPanel)
+                {
+                    RightPanelButton.IsChecked= true;
+                    ViewSettingBtn.IsChecked = false;
+                }
+                else if (panelState.RightPanel == PanelState.RightPanelState.ViewSettings)
+                {
+
+                    RightPanelButton.IsChecked = false;
+                    ViewSettingBtn.IsChecked = true;
+                }
+                else
+                {
+                    RightPanelButton.IsChecked = false;
+                    ViewSettingBtn.IsChecked = false;
+                }
+            }
+        }
+
+        #region Load Document
+        private void LoadDocument()
+        {
+            if (pdfViewControl.PDFView.Document == null)
+            {
+                return;
+            }
+            if(ViewModeBox!=null && ViewModeBox.SelectedIndex==1)
+            {
+                pdfViewControl.PDFView?.SetMouseMode(MouseModes.PanTool);
+            }
+            else
+            {
+                pdfViewControl.PDFView?.SetMouseMode(MouseModes.Viewer);
+            }
+           
+            pdfViewControl.PDFView?.Load();
+            pdfViewControl.PDFView?.SetShowLink(true);
+
+            pdfViewControl.PDFView.InfoChanged -= PdfViewer_InfoChanged;
+            pdfViewControl.PDFView.InfoChanged += PdfViewer_InfoChanged;
+            pdfViewControl.PDFView.AnnotCommandHandler -= PDFView_AnnotCommandHandler;
+            pdfViewControl.PDFView.AnnotCommandHandler += PDFView_AnnotCommandHandler;
+            pdfViewControl.PDFView.AnnotEditHandler -= PDFView_AnnotEditHandler;
+            pdfViewControl.PDFView.AnnotEditHandler += PDFView_AnnotEditHandler;
+            pdfViewControl.PDFView.UndoManager.PropertyChanged -= UndoManager_PropertyChanged;
+            pdfViewControl.PDFView.UndoManager.PropertyChanged += UndoManager_PropertyChanged;
+            pdfViewControl.PDFView.SetFormFieldHighlight(true);
+            PasswordUI.Closed -= PasswordUI_Closed;
+            PasswordUI.Canceled -= PasswordUI_Canceled;
+            PasswordUI.Confirmed -= PasswordUI_Confirmed;
+            PasswordUI.Closed += PasswordUI_Closed;
+            PasswordUI.Canceled += PasswordUI_Canceled;
+            PasswordUI.Confirmed += PasswordUI_Confirmed;
+
+            pdfViewControl.PDFView.ChangeFitMode(FitMode.FitWidth);
+            CPDFSaclingControl.InitWithPDFViewer(pdfViewControl.PDFView);
+            CPDFSaclingControl.SetZoomTextBoxText(string.Format("{0}", (int)(pdfViewControl.PDFView.ZoomFactor * 100)));
+
+            BotaSideTool.InitWithPDFViewer(pdfViewControl.PDFView);
+            BotaSideTool.SelectBotaTool(BOTATools.Thumbnail);
+            ViewSettingBtn.IsChecked = false;
+
+            LoadMeasureRes();
+        }
+
+        private void PDFView_AnnotEditHandler(object sender, List<AnnotEditEvent> e)
+        {
+            BotaSideTool.LoadAnnotationList();
+        }
+
+        private void LoadDefaultDocument()
+        {
+            string defaultFilePath = "PDF32000_2008.pdf";
+            pdfViewControl = new PDFViewControl();
+            pdfViewControl.PDFView.InitDocument(defaultFilePath);
+            LoadDocument();
+        }
+        #endregion
+
+        #region Password
+        private void PasswordUI_Confirmed(object sender, string e)
+        {
+            if (passwordViewer != null && passwordViewer.PDFView != null && passwordViewer.PDFView.Document != null)
+            {
+                passwordViewer.PDFView.Document.UnlockWithPassword(e);
+                if (passwordViewer.PDFView.Document.IsLocked == false)
+                {
+                    PasswordUI.SetShowError("", Visibility.Collapsed);
+                    PasswordUI.ClearPassword();
+                    PasswordUI.Visibility = Visibility.Collapsed;
+                    PopupBorder.Visibility = Visibility.Collapsed;
+                    pdfViewControl = passwordViewer;
+                    LoadDocument();
+                }
+                else
+                {
+                    PasswordUI.SetShowError("Wrong Password", Visibility.Visible);
+                }
+            }
+        }
+
+        private void PasswordUI_Canceled(object sender, EventArgs e)
+        {
+            PopupBorder.Visibility = Visibility.Collapsed;
+            PasswordUI.Visibility = Visibility.Collapsed;
+        }
+
+        private void PasswordUI_Closed(object sender, EventArgs e)
+        {
+            PopupBorder.Visibility = Visibility.Collapsed;
+            PasswordUI.Visibility = Visibility.Collapsed;
+        }
+        #endregion
+
+        #region Expand or Hide Panel 
+
+        private void ControlLeftPanel()
+        {
+            if (LeftToolPanelButton != null)
+            {
+                bool isExpand = LeftToolPanelButton.IsChecked == true;
+                ExpandLeftPanel(isExpand);
+            }
+        }
+
+        private void ExpandLeftPanel(bool isExpand)
+        {
+            BotaSideTool.Visibility = isExpand ? Visibility.Visible : Visibility.Collapsed;
+            Splitter.Visibility = isExpand ? Visibility.Visible : Visibility.Collapsed;
+            if (isExpand)
+            {
+                BodyGrid.ColumnDefinitions[0].Width = new GridLength(260);
+                BodyGrid.ColumnDefinitions[1].Width = new GridLength(15);
+            }
+            else
+            {
+                BodyGrid.ColumnDefinitions[0].Width = new GridLength(0);
+                BodyGrid.ColumnDefinitions[1].Width = new GridLength(0);
+            }
+        }
+
+        private void ExpandSearchBtn_Click(object sender, RoutedEventArgs e)
+        {
+            LeftToolPanelButton.IsChecked = true;
+            ExpandLeftPanel(true);
+            BotaSideTool.SelectBotaTool(BOTATools.Search);
+        }
+
+        private void LeftToolPanelButton_Click(object sender, RoutedEventArgs e)
+        {
+            ToggleButton expandBtn = sender as ToggleButton;
+            if (expandBtn != null)
+            {
+                bool isExpand = expandBtn.IsChecked == true;
+                ExpandLeftPanel(isExpand);
+            }
+        }
+
+        #endregion
+
+        #region UI
+        private double CheckZoomLevel(double zoom, bool IsGrowth)
+        {
+            double standardZoom = 100;
+            if (zoom <= 0.01)
+            {
+                return 0.01;
+            }
+            if (zoom >= 10)
+            {
+                return 10;
+            }
+
+            zoom *= 100;
+            for (int i = 0; i < zoomLevelList.Length - 1; i++)
+            {
+                if (zoom > zoomLevelList[i] && zoom <= zoomLevelList[i + 1] && IsGrowth)
+                {
+                    standardZoom = zoomLevelList[i + 1];
+                    break;
+                }
+                if (zoom >= zoomLevelList[i] && zoom < zoomLevelList[i + 1] && !IsGrowth)
+                {
+                    standardZoom = zoomLevelList[i];
+                    break;
+                }
+            }
+            return standardZoom / 100;
+        }
+
+        private void ShowViewSettings()
+        {
+            if (RightPanelButton != null)
+            {
+                if (RightPanelButton.IsChecked == true)
+                {
+                    RightPanelButton.IsChecked = false;
+                    measureControl.ExpandRightPropertyPanel(Visibility.Collapsed);
+                }
+            }
+            if (ViewSettingBtn != null)
+            {
+                if (ViewSettingBtn.IsChecked == true)
+                {
+                    measureControl.ExpandViewSettings(Visibility.Visible);
+                }
+                else
+                {
+                    measureControl.ExpandViewSettings(Visibility.Collapsed);
+                    panelState.RightPanel = RightPanelState.None;
+                }
+            }
+        }
+
+        private void ControlRightPanel()
+        {
+            if (ViewSettingBtn != null)
+            {
+                if (ViewSettingBtn.IsChecked == true)
+                {
+                    ViewSettingBtn.IsChecked = false;
+                    measureControl.ExpandViewSettings(Visibility.Collapsed);
+                }
+            }
+            if (RightPanelButton != null)
+            {
+                if (RightPanelButton.IsChecked == true)
+                {
+                    if (measureControl.measurePropertyControl != null)
+                    {
+                        measureControl.ExpandRightPropertyPanel(Visibility.Visible);
+                        if ((bool)ViewSettingBtn.IsChecked)
+                        {
+                            ViewSettingBtn.IsChecked = false;
+                        }
+                    }
+                }
+                else
+                {
+                    measureControl.ExpandRightPropertyPanel(Visibility.Collapsed);
+                }
+            }
+        }
+
+        private void ViewSettingBtn_Click(object sender, RoutedEventArgs e)
+        {
+            ShowViewSettings();
+        }
+
+        private void RightPanelButton_Click(object sender, RoutedEventArgs e)
+        {
+            ControlRightPanel();
+        }
+
+        private void ZoomInBtn_Click(object sender, RoutedEventArgs e)
+        {
+            if (pdfViewControl != null)
+            {
+                double newZoom = CheckZoomLevel(pdfViewControl.PDFView.ZoomFactor + 0.01, true);
+                pdfViewControl.PDFView.Zoom(newZoom);
+            }
+        }
+
+        private void ZoomOutBtn_Click(object sender, RoutedEventArgs e)
+        {
+            if (pdfViewControl != null)
+            {
+                double newZoom = CheckZoomLevel(pdfViewControl.PDFView.ZoomFactor - 0.01, false);
+                pdfViewControl.PDFView.Zoom(newZoom);
+            }
+        }
+
+        private void NextPageBorder_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+        {
+            pdfViewControl.PDFView?.GoToPage(pdfViewControl.PDFView.CurrentIndex + 1);
+        }
+
+        private void PrevPageBorder_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+        {
+            pdfViewControl.PDFView?.GoToPage(pdfViewControl.PDFView.CurrentIndex - 1);
+        }
+
+        private void PageInfoBtn_Click(object sender, RoutedEventArgs e)
+        {
+            PasswordUI.Visibility = Visibility.Collapsed;
+            FileInfoUI.Visibility = Visibility.Visible;
+            FileInfoControl.InitWithPDFViewer(pdfViewControl.PDFView);
+            PopupBorder.Visibility = Visibility.Visible;
+        }
+
+        private void FileInfoCloseBtn_Click(object sender, RoutedEventArgs e)
+        {
+            PopupBorder.Visibility = Visibility.Collapsed;
+        }
+        #endregion
+
+        #region Open and save file
+
+        /// <summary>
+        /// Save the file to another PDF file.
+        /// </summary>
+        public void SaveAsFile()
+        {
+            {
+                if (pdfViewControl != null && pdfViewControl.PDFView != null && pdfViewControl.PDFView.Document != null)
+                {
+                    CPDFDocument pdfDoc = pdfViewControl.PDFView.Document;
+                    SaveFileDialog saveDialog = new SaveFileDialog();
+                    saveDialog.Filter = "(*.pdf)|*.pdf";
+                    saveDialog.DefaultExt = ".pdf";
+                    saveDialog.OverwritePrompt = true;
+
+                    if (saveDialog.ShowDialog() == true)
+                    {
+                        pdfDoc.WriteToFilePath(saveDialog.FileName);
+                    }
+                }
+            }
+        }
+
+        private void SaveFile()
+        {
+            if (pdfViewControl != null && pdfViewControl.PDFView != null && pdfViewControl.PDFView.Document != null)
+            {
+                CPDFDocument pdfDoc = pdfViewControl.PDFView.Document;
+                if (pdfDoc.WriteToLoadedPath())
+                {
+                    pdfViewControl.PDFView.UndoManager.CanSave = false;
+                    return;
+                }
+
+                SaveFileDialog saveDialog = new SaveFileDialog();
+                saveDialog.Filter = "(*.pdf)|*.pdf";
+                saveDialog.DefaultExt = ".pdf";
+                saveDialog.OverwritePrompt = true;
+
+                if (saveDialog.ShowDialog() == true)
+                {
+                    if (pdfDoc.WriteToFilePath(saveDialog.FileName))
+                    {
+                        pdfViewControl.PDFView.UndoManager.CanSave = false;
+                    }
+                }
+            }
+        }
+
+        private void OpenFile()
+        {
+            string filePath = CommonHelper.GetExistedPathOrEmpty();
+            if (!string.IsNullOrEmpty(filePath) && pdfViewControl != null)
+            {
+                if (pdfViewControl.PDFView != null && pdfViewControl.PDFView.Document != null)
+                {
+                    string oldFilePath = pdfViewControl.PDFView.Document.FilePath;
+                    if (oldFilePath.ToLower() == filePath.ToLower())
+                    {
+                        return;
+                    }
+                }
+
+                passwordViewer = new PDFViewControl();
+                passwordViewer.PDFView.InitDocument(filePath);
+                if (passwordViewer.PDFView.Document == null)
+                {
+                    MessageBox.Show("Open File Failed");
+                    return;
+                }
+
+                if (passwordViewer.PDFView.Document.IsLocked)
+                {
+                    PasswordUI.SetShowText(System.IO.Path.GetFileName(filePath) + " password encrypted.");
+                    PasswordUI.ClearPassword();
+                    PopupBorder.Visibility = Visibility.Visible;
+                    PasswordUI.Visibility = Visibility.Visible;
+                }
+                else
+                {
+                    pdfViewControl = passwordViewer;
+                    LoadDocument();
+                }
+            }
+        }
+
+        private void OpenFile_Click(object sender, RoutedEventArgs e)
+        {
+            OpenFile();
+        }
+
+        private void SaveFileBtn_Click(object sender, RoutedEventArgs e)
+        {
+            SaveFile();
+        }
+
+        #endregion
+
+        #region Context Menu
+
+        private void ExtraImage_Click(object sender, RoutedEventArgs e)
+        {
+            System.Windows.Forms.FolderBrowserDialog folderDialog = new System.Windows.Forms.FolderBrowserDialog();
+            if (folderDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
+            {
+                string choosePath = folderDialog.SelectedPath;
+                string openPath = choosePath;
+                Dictionary<int, List<Bitmap>> imageDict = pdfViewControl.PDFView?.GetSelectedImages();
+
+                if (imageDict != null && imageDict.Count > 0)
+                {
+                    foreach (int pageIndex in imageDict.Keys)
+                    {
+                        List<Bitmap> imageList = imageDict[pageIndex];
+                        foreach (Bitmap image in imageList)
+                        {
+                            string savePath = Path.Combine(choosePath, Guid.NewGuid() + ".jpg");
+                            image.Save(savePath, System.Drawing.Imaging.ImageFormat.Jpeg);
+                            openPath = savePath;
+                        }
+                    }
+                }
+                Process.Start("explorer", "/select,\"" + openPath + "\"");
+            }
+        }
+
+        private void CopyImage_Click(object sender, RoutedEventArgs e)
+        {
+            Dictionary<int, List<Bitmap>> imageDict = pdfViewControl.PDFView?.GetSelectedImages();
+
+            if (imageDict != null && imageDict.Count > 0)
+            {
+                foreach (int pageIndex in imageDict.Keys)
+                {
+                    List<Bitmap> imageList = imageDict[pageIndex];
+                    foreach (Bitmap image in imageList)
+                    {
+                        MemoryStream ms = new MemoryStream();
+                        image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
+                        BitmapImage imageData = new BitmapImage();
+                        imageData.BeginInit();
+                        imageData.StreamSource = ms;
+                        imageData.CacheOption = BitmapCacheOption.OnLoad;
+                        imageData.EndInit();
+                        imageData.Freeze();
+                        Clipboard.SetImage(imageData);
+                        break;
+                    }
+                }
+            }
+        }
+
+        private void PDFView_AnnotCommandHandler(object sender, AnnotCommandArgs e)
+        {
+            if (e != null && e.CommandType == CommandType.Context)
+            {
+                if (e.PressOnSelectedText)
+                {
+                    e.Handle = true;
+                    e.PopupMenu = new ContextMenu();
+                    e.PopupMenu.Items.Add(new MenuItem() { Header = "Copy", Command = ApplicationCommands.Copy, CommandTarget = (UIElement)sender });
+                }
+                else if (e.CommandTarget == TargetType.ImageSelection)
+                {
+                    if (pdfViewControl != null && pdfViewControl.PDFView != null && pdfViewControl.PDFView.GetSelectImageCount() > 0)
+                    {
+                        e.Handle = true;
+                        e.PopupMenu = new ContextMenu();
+
+                        MenuItem imageCopyMenu = new MenuItem();
+                        imageCopyMenu = new MenuItem();
+                        imageCopyMenu.Header = "Copy Images";
+                        WeakEventManager<MenuItem, RoutedEventArgs>.AddHandler(imageCopyMenu, "Click", CopyImage_Click);
+                        imageCopyMenu.CommandParameter = e;
+                        e.PopupMenu.Items.Add(imageCopyMenu);
+
+                        MenuItem imageExtraMenu = new MenuItem();
+                        imageExtraMenu = new MenuItem();
+                        imageExtraMenu.Header = "Extract Images";
+                        WeakEventManager<MenuItem, RoutedEventArgs>.AddHandler(imageExtraMenu, "Click", ExtraImage_Click);
+                        imageExtraMenu.CommandParameter = e;
+                        e.PopupMenu.Items.Add(imageExtraMenu);
+                    }
+                }
+                else
+                {
+                    e.Handle = true;
+                    e.PopupMenu = new ContextMenu();
+                    //if (pdfViewControl.CheckHasForm())
+
+                    MenuItem fitWidthMenu = new MenuItem();
+                    fitWidthMenu.Header = "Automatically Resize";
+                    fitWidthMenu.Click += (o, p) =>
+                    {
+                        if (pdfViewControl != null)
+                        {
+                            pdfViewControl.PDFView?.ChangeFitMode(FitMode.FitWidth);
+                        }
+                    };
+
+                    e.PopupMenu.Items.Add(fitWidthMenu);
+
+                    MenuItem fitSizeMenu = new MenuItem();
+                    fitSizeMenu.Header = "Actual Size";
+                    fitSizeMenu.Click += (o, p) =>
+                    {
+                        if (pdfViewControl != null)
+                        {
+                            pdfViewControl.PDFView?.ChangeFitMode(FitMode.FitSize);
+                        }
+                    };
+
+                    e.PopupMenu.Items.Add(fitSizeMenu);
+
+                    MenuItem zoomInMenu = new MenuItem();
+                    zoomInMenu.Header = "Zoom In";
+                    zoomInMenu.Click += (o, p) =>
+                    {
+                        if (pdfViewControl != null)
+                        {
+                            double newZoom = CheckZoomLevel(pdfViewControl.PDFView.ZoomFactor + 0.01, true);
+                            pdfViewControl.PDFView?.Zoom(newZoom);
+                        }
+                    };
+
+                    e.PopupMenu.Items.Add(zoomInMenu);
+
+                    MenuItem zoomOutMenu = new MenuItem();
+                    zoomOutMenu.Header = "Zoom Out";
+                    zoomOutMenu.Click += (o, p) =>
+                    {
+                        if (pdfViewControl != null)
+                        {
+                            double newZoom = CheckZoomLevel(pdfViewControl.PDFView.ZoomFactor - 0.01, false);
+                            pdfViewControl.PDFView?.Zoom(newZoom);
+                        }
+                    };
+
+                    e.PopupMenu.Items.Add(zoomOutMenu);
+                    e.PopupMenu.Items.Add(new Separator());
+
+                    MenuItem singleView = new MenuItem();
+                    singleView.Header = "Single Page";
+                    singleView.Click += (o, p) =>
+                    {
+                        if (pdfViewControl != null)
+                        {
+                            pdfViewControl.PDFView?.ChangeViewMode(ViewMode.Single);
+                        }
+                    };
+
+                    e.PopupMenu.Items.Add(singleView);
+
+                    MenuItem singleContinuousView = new MenuItem();
+                    singleContinuousView.Header = "Single Page Continuous";
+                    singleContinuousView.Click += (o, p) =>
+                    {
+                        if (pdfViewControl != null)
+                        {
+                            pdfViewControl.PDFView?.ChangeViewMode(ViewMode.SingleContinuous);
+                        }
+                    };
+
+                    e.PopupMenu.Items.Add(singleContinuousView);
+
+                    MenuItem doubleView = new MenuItem();
+                    doubleView.Header = "Two Pages";
+                    doubleView.Click += (o, p) =>
+                    {
+                        if (pdfViewControl != null)
+                        {
+                            pdfViewControl.PDFView?.ChangeViewMode(ViewMode.Double);
+                        }
+                    };
+
+                    e.PopupMenu.Items.Add(doubleView);
+
+                    MenuItem doubleContinuousView = new MenuItem();
+                    doubleContinuousView.Header = "Two Pages Continuous";
+                    doubleContinuousView.Click += (o, p) =>
+                    {
+                        if (pdfViewControl != null)
+                        {
+                            pdfViewControl.PDFView?.ChangeViewMode(ViewMode.DoubleContinuous);
+                        }
+                    };
+                    e.PopupMenu.Items.Add(doubleContinuousView);
+
+                    {
+                        MenuItem resetForms = new MenuItem();
+                        resetForms.Header = "Reset Forms";
+                        resetForms.Click += (o, p) =>
+                        {
+                            if (pdfViewControl != null)
+                            {
+                                pdfViewControl.PDFView?.ResetForm(null);
+                            }
+                        };
+                        e.PopupMenu.Items.Add(new Separator());
+                        e.PopupMenu.Items.Add(resetForms);
+                    }
+                }
+            }
+
+            if (e != null && e.CommandType == CommandType.Copy)
+            {
+                e.DoCommand();
+            }
+        }
+
+        #endregion
+
+        #region Close Window
+
+        protected override void OnClosing(CancelEventArgs e)
+        {
+            if (pdfViewControl.PDFView.UndoManager.CanSave)
+            {
+                MessageBoxResult result = MessageBox.Show("Do you want to save your changes before closing the application?", "Message", MessageBoxButton.YesNoCancel);
+                if (result == MessageBoxResult.Yes)
+                {
+                    SaveFile();
+                }
+                else if (result == MessageBoxResult.No)
+                {
+
+                }
+                else
+                {
+                    e.Cancel = true;
+                }
+            }
+        }
+
+        #endregion
+
+        #region PropertyChanged
+
+        /// <summary>
+        /// Zoom
+        /// </summary> 
+        private void PdfViewer_InfoChanged(object sender, KeyValuePair<string, object> e)
+        {
+            if (e.Key == "Zoom")
+            {
+                CPDFSaclingControl.SetZoomTextBoxText(string.Format("{0}", (int)((double)e.Value * 100)));
+            }
+        }
+
+        /// <summary>
+        /// Undo Redo Event Noitfy
+        /// </summary>
+        private void UndoManager_PropertyChanged(object sender, PropertyChangedEventArgs e)
+        {
+            OnPropertyChanged(e.PropertyName);
+        }
+
+        protected void OnPropertyChanged([CallerMemberName] string name = null)
+        {
+            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
+        }
+
+        #endregion
+
+        #region Shortcut  
+
+        private void CommandBinding_Executed_Open(object sender, ExecutedRoutedEventArgs e)
+        {
+            OpenFile();
+        }
+
+        private void CommandBinding_Executed_Save(object sender, ExecutedRoutedEventArgs e)
+        {
+            if (CanSave)
+            {
+                SaveFile();
+            }
+        }
+
+        private void CommandBinding_Executed_SaveAs(object sender, ExecutedRoutedEventArgs e)
+        {
+            SaveAsFile();
+        }
+
+        private void CommandBinding_Executed_ControlLeftPanel(object sender, ExecutedRoutedEventArgs e)
+        {
+            LeftToolPanelButton.IsChecked = !LeftToolPanelButton.IsChecked;
+            ControlLeftPanel();
+        }
+
+        private void CommandBinding_Executed_Bookmark(object sender, ExecutedRoutedEventArgs e)
+        {
+            ExpandLeftPanel(true);
+            LeftToolPanelButton.IsChecked = true;
+            BotaSideTool.SelectBotaTool(BOTATools.Bookmark);
+        }
+
+        private void CommandBinding_Executed_Outline(object sender, ExecutedRoutedEventArgs e)
+        {
+            ExpandLeftPanel(true);
+            LeftToolPanelButton.IsChecked = true;
+            BotaSideTool.SelectBotaTool(BOTATools.Outline);
+        }
+
+        private void CommandBinding_Executed_Thumbnail(object sender, ExecutedRoutedEventArgs e)
+        {
+            ExpandLeftPanel(true);
+            LeftToolPanelButton.IsChecked = true;
+            BotaSideTool.SelectBotaTool(BOTATools.Thumbnail);
+        }
+
+        private void CommandBinding_Executed_Search(object sender, ExecutedRoutedEventArgs e)
+        {
+            ExpandLeftPanel(true);
+            LeftToolPanelButton.IsChecked = true;
+            BotaSideTool.SelectBotaTool(BOTATools.Search);
+        }
+        private void CommandBinding_Executed_ScaleAdd(object sender, ExecutedRoutedEventArgs e)
+        {
+            double newZoom = CheckZoomLevel(pdfViewControl.PDFView.ZoomFactor + 0.01, true);
+            pdfViewControl.PDFView?.Zoom(newZoom);
+        }
+
+        private void CommandBinding_Executed_ScaleSubtract(object sender, ExecutedRoutedEventArgs e)
+        {
+            double newZoom = CheckZoomLevel(pdfViewControl.PDFView.ZoomFactor - 0.01, false);
+            pdfViewControl.PDFView?.Zoom(newZoom);
+        }
+
+        private void CommandBinding_Executed_DisplaySettings(object sender, ExecutedRoutedEventArgs e)
+        {
+            ViewSettingBtn.IsChecked = !ViewSettingBtn.IsChecked;
+            ShowViewSettings();
+        }
+
+        private void CommandBinding_Executed_DocumentInfo(object sender, ExecutedRoutedEventArgs e)
+        {
+            if (PopupBorder.Visibility != Visibility.Visible)
+            {
+                PasswordUI.Visibility = Visibility.Collapsed;
+                FileInfoUI.Visibility = Visibility.Visible;
+                FileInfoControl.InitWithPDFViewer(pdfViewControl.PDFView);
+                PopupBorder.Visibility = Visibility.Visible;
+            }
+            else
+            {
+                FileInfoUI.Visibility = Visibility.Collapsed;
+                PopupBorder.Visibility = Visibility.Collapsed;
+            }
+        }
+        #endregion
+
+        private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
+        {
+
+        }
+
+        #region Measure
+
+        private void LoadMeasureRes()
+        {
+            panelState.RightPanel = RightPanelState.None;
+            FloatPageTool.Visibility = Visibility.Collapsed;
+            PDFGrid.Child = null;
+            RightPanelButton.Visibility = Visibility.Visible;
+            PDFGrid.Child = measureControl;
+            displayPanel.InitWithPDFViewer(pdfViewControl.PDFView);
+            measureControl.InitWithPDFViewer(pdfViewControl, pdfViewControl.PDFView);
+            measureControl.SetSettingsControl(displayPanel);
+            measureControl.ExpandEvent -= MeasureControl_ExpandEvent;
+            measureControl.ExpandEvent += MeasureControl_ExpandEvent;
+        }
+
+        private void MeasureControl_ExpandEvent(object sender, EventArgs e)
+        {
+            RightPanelButton.IsChecked = true;
+            ControlRightPanel();
+        }
+
+        private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+            var item = (sender as ComboBox).SelectedItem as ComboBoxItem;
+            if ((string)item.Content == "Viewer")
+            {
+                panelState.RightPanel = RightPanelState.None;
+                measureControl.ClearAllToolState();
+                measureControl.ExpandNullRightPropertyPanel(Visibility.Collapsed);
+                RightPanelButton.IsChecked = false;
+                if (pdfViewControl != null && pdfViewControl.PDFView != null)
+                {
+                    pdfViewControl.PDFView.SetMouseMode(MouseModes.Viewer);
+                }
+                RightPanelButton.Visibility = Visibility.Collapsed;
+                measureControl.ClearViewerControl();
+                PDFGrid.Child = pdfViewControl;
+                FloatPageTool.Visibility = Visibility.Visible;
+                FloatPageTool.InitWithPDFViewer(pdfViewControl.PDFView);
+            }
+            else if ((string)item.Content == "Measurement")
+            {
+                LoadMeasureRes();
+                if (pdfViewControl != null && pdfViewControl.PDFView != null)
+                {
+                    pdfViewControl.PDFView.SetMouseMode(MouseModes.PanTool);
+                }
+            }
+        }
+
+
+        #endregion
+    }
+}

+ 164 - 0
Demo/Examples/Measure/Measure.csproj

@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{75A0C673-E1D8-4FCE-8804-95E4F0630200}</ProjectGuid>
+    <OutputType>WinExe</OutputType>
+    <RootNamespace>Measure</RootNamespace>
+    <AssemblyName>Forms_ComPDFKit</AssemblyName>
+    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <WarningLevel>4</WarningLevel>
+    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+    <Deterministic>true</Deterministic>
+    <NuGetPackageImportStamp>
+    </NuGetPackageImportStamp>
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>x64</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup>
+    <ApplicationIcon>ComPDFKit_Logo.ico</ApplicationIcon>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="PresentationFramework.Aero2, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <HintPath>..\packages\PresentationFramework.Aero2.1.0.1\lib\PresentationFramework.Aero2.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xaml">
+      <RequiredTargetFramework>4.0</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="WindowsBase" />
+    <Reference Include="PresentationCore" />
+    <Reference Include="PresentationFramework" />
+  </ItemGroup>
+  <ItemGroup>
+    <ApplicationDefinition Include="App.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </ApplicationDefinition>
+    <Page Include="MainWindow.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </Page>
+    <Compile Include="App.xaml.cs">
+      <DependentUpon>App.xaml</DependentUpon>
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="MainWindow.xaml.cs">
+      <DependentUpon>MainWindow.xaml</DependentUpon>
+      <SubType>Code</SubType>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Properties\AssemblyInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+    <Compile Include="Properties\Settings.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Settings.settings</DependentUpon>
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>
+    </Compile>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+    <None Include="packages.config" />
+    <None Include="PDF32000_2008.pdf">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+    <None Include="Properties\Settings.settings">
+      <Generator>SettingsSingleFileGenerator</Generator>
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\compdfkit_windows\ComPDFKit\ComPDFKitCSharp\ComPDFKit.Desk.csproj">
+      <Project>{56e518ad-c126-4b48-9a09-0a64c87020e4}</Project>
+      <Name>ComPDFKit.Desk</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\compdfkit_windows\ComPDFKit\ComPDFKitDesktop\ComPDFKit.Viewer\ComPDFKit.Viewer.csproj">
+      <Project>{18ec356d-8130-49d4-b4e6-ac290e1065b7}</Project>
+      <Name>ComPDFKit.Viewer</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Compdfkit_Tools\Compdfkit_Tools.csproj">
+      <Project>{9363bcb1-3a67-446a-8093-5708b86bf418}</Project>
+      <Name>Compdfkit_Tools</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="ComPDFKit_Logo.ico" />
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include=".NETFramework,Version=v4.6.1">
+      <Visible>False</Visible>
+      <ProductName>Microsoft .NET Framework 4.6.1 %28x86 和 x64%29</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="..\license_key_windows.xml">
+      <Link>license_key_windows.xml</Link>
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project>

二进制
Demo/Examples/Measure/PDF32000_2008.pdf


+ 55 - 0
Demo/Examples/Measure/Properties/AssemblyInfo.cs

@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("PDFMeasure")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("PDFMeasure")]
+[assembly: AssemblyCopyright("Copyright ©  2023")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+//若要开始生成可本地化的应用程序,请设置
+//.csproj 文件中的 <UICulture>CultureYouAreCodingWith</UICulture>
+//在 <PropertyGroup> 中。例如,如果你使用的是美国英语。
+//使用的是美国英语,请将 <UICulture> 设置为 en-US。  然后取消
+//对以下 NeutralResourceLanguage 特性的注释。  更新
+//以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+    ResourceDictionaryLocation.None, //主题特定资源词典所处位置
+                                     //(未在页面中找到资源时使用,
+                                     //或应用程序资源字典中找到时使用)
+    ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
+                                              //(未在页面中找到资源时使用,
+                                              //、应用程序或任何主题专用资源字典中找到时使用)
+)]
+
+
+// 程序集的版本信息由下列四个值组成: 
+//
+//      主版本
+//      次版本
+//      生成号
+//      修订号
+//
+//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.10.1.0")]
+[assembly: AssemblyFileVersion("1.10.1.0")]

+ 63 - 0
Demo/Examples/Measure/Properties/Resources.Designer.cs

@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     此代码由工具生成。
+//     运行时版本:4.0.30319.42000
+//
+//     对此文件的更改可能会导致不正确的行为,并且如果
+//     重新生成代码,这些更改将会丢失。
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Measure.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   一个强类型的资源类,用于查找本地化的字符串等。
+    /// </summary>
+    // 此类是由 StronglyTypedResourceBuilder
+    // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
+    // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
+    // (以 /str 作为命令选项),或重新生成 VS 项目。
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   返回此类使用的缓存的 ResourceManager 实例。
+        /// </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("Measure.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   重写当前线程的 CurrentUICulture 属性,对
+        ///   使用此强类型资源类的所有资源查找执行重写。
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+    }
+}

+ 117 - 0
Demo/Examples/Measure/Properties/Resources.resx

@@ -0,0 +1,117 @@
+<?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.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: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" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+            </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" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+            </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=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>

+ 26 - 0
Demo/Examples/Measure/Properties/Settings.Designer.cs

@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     此代码由工具生成。
+//     运行时版本:4.0.30319.42000
+//
+//     对此文件的更改可能会导致不正确的行为,并且如果
+//     重新生成代码,这些更改将会丢失。
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Measure.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+    }
+}

+ 7 - 0
Demo/Examples/Measure/Properties/Settings.settings

@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
+  <Profiles>
+    <Profile Name="(Default)" />
+  </Profiles>
+  <Settings />
+</SettingsFile>

+ 5 - 0
Demo/Examples/Measure/packages.config

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="ComPDFKit.NetFramework" version="1.11.0" targetFramework="net461" />
+  <package id="PresentationFramework.Aero2" version="1.0.1" targetFramework="net461" />
+</packages>

+ 1 - 0
Demo/Examples/PDFViewer/MainPage.xaml

@@ -182,6 +182,7 @@
                     <ComboBoxItem Tag="Content Editor" Content="{Binding Converter={StaticResource CommonResourceConverter},ConverterParameter=Func_ContentEditor}"></ComboBoxItem>
                     <ComboBoxItem Tag="Document Editor" Content="{Binding Converter={StaticResource CommonResourceConverter},ConverterParameter=Func_DocEditor}"></ComboBoxItem>
                     <ComboBoxItem Tag="Digital Signature" Content="{Binding Converter={StaticResource CommonResourceConverter},ConverterParameter=Func_Signatures}"></ComboBoxItem>
+                    <ComboBoxItem Tag="Measurement" Content="Measurement"></ComboBoxItem>
                 </ComboBox>
 
                 <StackPanel Orientation="Horizontal" Grid.Column="2">

+ 25 - 4
Demo/Examples/PDFViewer/MainPage.xaml.cs

@@ -15,6 +15,7 @@ using ComPDFKitViewer.PdfViewer;
 using Microsoft.Win32;
 using System.Windows.Input;
 using ComPDFKitViewer.AnnotEvent;
+using Compdfkit_Tools.Measure;
 
 namespace PDFViewer
 {
@@ -32,6 +33,7 @@ namespace PDFViewer
         private FormControl formControl = new FormControl();
         private ContentEditControl contentEditControl = new ContentEditControl();
         private PageEditControl pageEditControl = new PageEditControl();
+        private MeasureControl measureControl = new MeasureControl();
         private DigitalSignatureControl digitalSignatureControl = new DigitalSignatureControl();
         private SignatureStatusBarControl signatureStatusBarControl = new SignatureStatusBarControl();
         private CPDFBOTABarControl botaBarControl = new CPDFBOTABarControl();
@@ -118,7 +120,7 @@ namespace PDFViewer
         public MainPage()
         {
             InitializeComponent();
-            this.DataContext = this; 
+            this.DataContext = this;
         }
         #endregion
 
@@ -131,7 +133,7 @@ namespace PDFViewer
         public void InitWithFilePath(string filePath)
         {
             pdfViewer = new PDFViewControl();
-            pdfViewer.PDFView.InitDocument(filePath); 
+            pdfViewer.PDFView.InitDocument(filePath);
         }
 
         public void InitWithDocument(CPDFDocument document)
@@ -227,6 +229,9 @@ namespace PDFViewer
                     case "Content Editor":
                         ModeComboBox.SelectedIndex = 3;
                         break;
+                    case "Measurement":
+                        ModeComboBox.SelectedIndex = 6;
+                        break;
                     default:
                         break;
                 }
@@ -452,6 +457,12 @@ namespace PDFViewer
                 digitalSignatureControl.ClearViewerControl();
                 botaBarControl.RemoveBOTAContent(BOTATools.Signature);
             }
+            else if (currentMode == "Measurement")
+            {
+                RightPanelButton.Visibility = Visibility.Visible;
+                measureControl.ClearAllToolState();
+                measureControl.ClearViewerControl();
+            }
 
             if (item.Tag as string == "Viewer")
             {
@@ -555,6 +566,16 @@ namespace PDFViewer
                     digitalSignatureControl.AfterFillSignature += DigitalSignatureControl_AfterFillSignature;
                 }
             }
+            else if (item.Tag as string == "Measurement")
+            {
+                if (contentEditControl.pdfContentEditControl != null && contentEditControl.PdfViewControl.PDFView != null)
+                {
+                    RightPanelButton.Visibility = Visibility.Visible;
+                    PDFGrid.Child = measureControl;
+                    pdfViewer.PDFView.SetMouseMode(MouseModes.PanTool);
+                    measureControl.InitWithPDFViewer(pdfViewer, pdfViewer.PDFView);
+                }
+            }
             currentMode = item.Tag as string;
             RightToolPanelButtonIsChecked = false;
         }
@@ -613,7 +634,7 @@ namespace PDFViewer
 
             CPDFTitleBarControl.SaveFileEvent -= CPDFTitleBarControl_SaveFileEvent;
             CPDFTitleBarControl.SaveFileEvent += CPDFTitleBarControl_SaveFileEvent;
-            
+
             CPDFTitleBarControl.FlattenEvent -= CPDFTitleBarControl_FlattenEvent;
             CPDFTitleBarControl.FlattenEvent += CPDFTitleBarControl_FlattenEvent;
         }
@@ -632,7 +653,7 @@ namespace PDFViewer
                     }
                     CPDFDocument document = CPDFDocument.InitWithFilePath(pdfViewer.PDFView.Document.FilePath);
                     if (document?.WriteFlattenToFilePath(savePath) == true)
-                    {  
+                    {
                         System.Diagnostics.Process.Start("Explorer.exe", "/select," + savePath);
                     }
                     document?.Release();

+ 8 - 6
Demo/Examples/PDFViewer/PDFViewer.csproj

@@ -43,12 +43,6 @@
     <ApplicationIcon>ComPDFKit_Logo.ico</ApplicationIcon>
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="ComPDFKit.Desk, Version=1.11.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\ComPDFKit.NetFramework.1.11.0\lib\ComPDFKit.Desk.dll</HintPath>
-    </Reference>
-    <Reference Include="ComPDFKit.Viewer, Version=1.11.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\ComPDFKit.NetFramework.1.11.0\lib\ComPDFKit.Viewer.dll</HintPath>
-    </Reference>
     <Reference Include="Dragablz">
       <HintPath>.\Dragablz.dll</HintPath>
     </Reference>
@@ -187,6 +181,14 @@
     <Resource Include="ComPDFKit_Logo.ico" />
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\..\..\compdfkit_windows\ComPDFKit\ComPDFKitCSharp\ComPDFKit.Desk.csproj">
+      <Project>{56e518ad-c126-4b48-9a09-0a64c87020e4}</Project>
+      <Name>ComPDFKit.Desk</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\compdfkit_windows\ComPDFKit\ComPDFKitDesktop\ComPDFKit.Viewer\ComPDFKit.Viewer.csproj">
+      <Project>{18ec356d-8130-49d4-b4e6-ac290e1065b7}</Project>
+      <Name>ComPDFKit.Viewer</Name>
+    </ProjectReference>
     <ProjectReference Include="..\Compdfkit_Tools\Compdfkit_Tools.csproj">
       <Project>{9363bcb1-3a67-446a-8093-5708b86bf418}</Project>
       <Name>Compdfkit_Tools</Name>