169 Commits 1df0151577 ... c82ea76972

Autor SHA1 Mensaje Fecha
  liyijie c82ea76972 Merge branch 'compdfkit_demo_win_dev' into compdfkit_demo_win_dev_pdftech hace 1 mes
  liyuxuan 145a9e8e34 ComPDFKit.Tool(Win) - 修复直线测量原部分地方漏掉缩放比问题 hace 2 meses
  liyuxuan f19a6e13da ComPDFKit.Tool(Win) - 文字替换 FindPrevious函数索引增加异常判断 hace 2 meses
  liyijie 8525049312 Merge branch 'compdfkit_demo_win_dev' of http://git.kdan.cc:8865/Others/kmpdfkit_demo into compdfkit_demo_win_dev hace 2 meses
  liyijie 7a1c0e5d91 ComPDF.Tool(Win)-常规模式下字符在图片上,字符无法选择问题修复 hace 2 meses
  liyuxuan a7231125a1 ComPDFKit.Tool(Win) - 调整更新弹出文字框逻辑 hace 2 meses
  liyuxuan afbc56e4c5 ComPDFKit.Tool(Win) - 粘贴形状注释时获取注释范围下文字 hace 2 meses
  liyuxuan e3b0ba2bdc ComPDFKit.Tool(Win) - 修复直线测量移动效果问题 hace 2 meses
  liyuxuan 26839cd4c0 ComPDFKit.Tool(Win) - 补充图片选择控制 hace 2 meses
  liyuxuan e3d4b57fbf ComPDFKit.Tool(Win) - 补充弹出输入框控件名称 hace 2 meses
  liyuxuan 4bd055d5da ComPDFKit.Tool(Win) - 修改弹出输入框时部分字体出现输入方块乱码问题 hace 2 meses
  liyuxuan 6e3f3afafb ComPDFKit.Tool(Win) - 修改鼠标按下判断 hace 2 meses
  liyuxuan 5a23e37bf5 ComPDFKit.Tool(Win) - 修复设置带黑色图章透明度旋转后还原问题 hace 2 meses
  liyuxuan 07e039d564 ComPDFKit.Tool(Win) - 修复文字选择时若鼠标拖到页面范围外松开会将前面所有页面文字选中 hace 2 meses
  liyuxuan 9194dc0e09 ComPDFKit.Tool(Win) - 修复直线测量Undo,Redo问题 hace 2 meses
  liyuxuan 4f2ea5e136 ComPDFKit.Tool(Win) - 修复直线测量按住控制点旋转时效果异常问题;修复直线测量注释从右往左创建后第一次点击中间点拖拽时效果异常问题 hace 2 meses
  liyuxuan 51aec26b95 ComPDFKit.Tool(Win) - 修复测量创建时跨页问题;折线和多边形少于3个点不保存; hace 2 meses
  liyuxuan 752cdcb637 ComPDFKit.Tool(Win) - 表单多选移动框选增加控制开关 hace 2 meses
  liyuxuan 8ac90a1121 ComPDFKit.Tool(Win) - 表单多选移动框选调整 hace 2 meses
  liyuxuan b3c71f7e2e ComPDFKit.Tool(Win) - 表单多选移动,等比调整大小,复制,粘贴,剪切,删除,多选Undo,Redo hace 2 meses
  liyuxuan 207dd493e8 ComPDFKit.Tool(Win) - 表单多选效果(能Ctrl多选,框选多选) hace 2 meses
  TangJinZhou 579cd45ce9 ComPDFKit.Demo - 修复数字签名列表右键菜单点击无效的问题 hace 2 meses
  liyuxuan 68109bcd26 ComPDFKit.Tool(Win) - 图章修复设置透明度为0并保存后Undo,Redo图章内容变白问题 hace 2 meses
  liuaoran 3eafe1c2ee Revert "ComPDFKit.Tools - 旋转框绘制" hace 2 meses
  liuaoran 0fcc887bc8 ComPDFKit.Tools - 旋转框绘制 hace 2 meses
  liyuxuan 6b0d17811c ComPDFKit.Tool(Win) - 增加表单创建时通知事件 hace 2 meses
  liyuxuan 4cbdc45bfc ComPDFKit.Tool(Win) - 表单List,ComboBox,Text,PushButton和FreeText字体名称设置改为新版本 hace 2 meses
  TangJinZhou 3251f716cb ComPDFKit.Demo - 移除多余刷新注释调用 hace 3 meses
  TangJinZhou 93b2ebb216 ComPDFKit.Demo(win) - 修复签名注释面板添加Ink注释大小不一致的问题 hace 3 meses
  TangJinZhou c31c21b91b ComPDFKit.Demo(win) - 修复使用签名注释面板添加注释崩溃的问题 hace 3 meses
  liyuxuan 8419fa0c98 ComPDFKit.Tool(Win) - 图章Undo,Redo支持透明度和顺时针逆时针旋转90度还原 hace 3 meses
  liuaoran 0aaa751489 ComPDFKit.Demo(win) - 修复打印异常情况:可打印区域大于纸张本身尺寸 hace 3 meses
  liuaoran 0d7ce654df ComPDFKit.Demo(win) - 优化打印功能 hace 3 meses
  TangJinZhou 4e70b485cd ComPDFKit.Demo(win) - 字体子集化开关需要默认打开 hace 3 meses
  TangJinZhou faa58272dc ComPDFKit.Demo(win) - 调整设置对话框版权信息时间 hace 3 meses
  liyuxuan eb27472686 ComPDFKit.Tool(Win) - 形状注释自动设置框选范围下文字为Content hace 3 meses
  liyuxuan 3e480a2300 ComPDFKit.Tool(Win) - 便签自定义AP设置 hace 3 meses
  liyuxuan e1fed2ee81 ComPDFKit.Tool(Win) - FreeText虚线框支持 hace 3 meses
  liyuxuan 99215853e8 ComPDFKit.Tool(Win) - 修复文件对比Tools层错误 hace 3 meses
  TangJinZhou 2e202fdba3 ComPDFKit.Tool(Win) - 修复Redact和Markup注释QuardRects设置错误的问题 hace 3 meses
  liyuxuan 4e221d11d4 ComPDFKit.Tool(win) - 修复橡皮擦擦除错误 hace 3 meses
  liyijie 933b1ae813 ComPDFKit.Tool(win)-滑动条更改事件 hace 3 meses
  liyijie a011a3e2c2 ComPDFKit.Tool(win)-补充选中框颜色参数 hace 3 meses
  liyuxuan a01670a387 ComPDFKit.Tool(win) - 点击时重置之前记录鼠标位置 hace 3 meses
  liyuxuan 9961eaf2ce ComPDFKit.Tool(win) - 按文字选择效果创建链接注释 hace 3 meses
  liyuxuan e5b29f4653 ComPDFKit.Tool(win) - 修改便签创建删除空便签问题 hace 3 meses
  liuaoran 850494ee37 ComPDFKit.Demo(win) - Merge branch 'compdfkit_demo_win' into compdfkit_demo_win_dev hace 3 meses
  liuaoran c57aef12e2 ComPDFKit(win) - 隐藏渲染卡顿优化 hace 3 meses
  liuaoran 709bd71e3e ComPDFKit(win) - 更新版本号 hace 3 meses
  liuaoran cc11f249b1 ComPDFKit(win) - 注释列表UI调整 hace 3 meses
  TangJinZhou c7b5b6bafa ComPDFKit.Demo(win) - 移除内容编辑Demo多余代码 hace 3 meses
  liyuxuan d0ce867d70 ComPDFKit.Tool(win) - 复制手绘属性参数更改 hace 3 meses
  TangJinZhou 09d455661f ComPDFKit.Demo(win) - 修复打印设置长短边距UI没有Tag的问题 hace 3 meses
  TangJinZhou 75724dee69 ComPDFKit.Demo(win) - 修复内容编辑多选时属性面板设置问题 hace 3 meses
  TangJinZhou fac0556d97 ComPDFKit.Tool(win) - 处理内容编多选后EditAreaList被刷新的问题; 增加获取当前编辑对象的接口 hace 3 meses
  youna 3561fb5adf ComPDFKit(win) - 多选 hace 3 meses
  TangJinZhou e1ef8eec3c ComPDFKit.Demo(win) - 注释列表支持缩放和展开 hace 3 meses
  TangJinZhou 6a77d241bc ComPDFKit.Demo(win) - 修复删除注释回复,回复列表没有刷新的问题; 修正文案 hace 3 meses
  TangJinZhou 4aec23cb3e ComPDFKit.Demo(win) - 修复使用右键菜单缩放页面后, 比例值不更新的问题 hace 3 meses
  liyuxuan 73efe54d2f ComPDFKit.Tool(win) - 创建的便签未输入内容时可以控制保存或不保存 hace 3 meses
  TangJinZhou c84e9b5933 ComPDFKit.Demo(win) - 移除多余渲染页面接口调用 hace 3 meses
  TangJinZhou d6ec6240a9 ComPDFKit.Demo(win) - 修复注释列表,Line注释绑定注释图标不正确的问题 hace 3 meses
  TangJinZhou b481889aa0 ComPDFKit.Demo(win) - 修复注释列表只能显示当前页面注释的问题,过滤掉Link注释 hace 3 meses
  liyuxuan e47271ad70 ComPDFKit.Tool(win) - 修复Undo/Redo 中便签图标还原不正确问题 hace 3 meses
  TangJinZhou f128f33256 ComPDFKit.Demo(win) - 处理内容编辑多选快捷键Ctrl和Shift hace 3 meses
  youna 7012457b86 ComPDFKit.Tools(win) - 回撤变更 hace 3 meses
  youna 579e80fb64 ComPDFKit(win) - 同步修改代码 hace 3 meses
  liyijie 3d03cccd40 Merge branch 'compdfkit_demo_win_dev' of http://git.kdan.cc:8865/Others/kmpdfkit_demo into compdfkit_demo_win_dev hace 3 meses
  liyijie 3fc7b9b75c ComPDFKit.Tool(win)-补充滑动条改变事件 hace 3 meses
  liyuxuan 329757079f ComPDFKit.Tool(win) - 手绘创建时显示效果增加虚线支持 hace 3 meses
  liyuxuan a0668aa71c ComPDFKit.Tool(win)-文件对比选中高亮效果 hace 3 meses
  liyuxuan 8c4510655f ComPDFKit.Tool(win)-便签图标和手绘虚线效果 hace 3 meses
  liyijie 88a62b00c6 ComPDFKit.Tool(win)-橡皮擦删除时返回索引异常修复(undo队列导致新删的索引为-2) hace 3 meses
  liyijie 68f52f08bb ComPDFKit.Tool(win)-多选拖拽逻辑优化 hace 3 meses
  TangJinZhou ca519fb154 ComPDFKit.Tool(win) - 修复Delete键删除文字问题 hace 3 meses
  liyijie 8b425ffea8 ComPDFKit.Tool(win)-当选中输入框,然后滑动到其他页导致无法输入任何内容,补充安全检查防止在对象为空 hace 3 meses
  liyijie 316c59bdb2 ComPDFKit.Tool(win)-删除图片取消选中 hace 3 meses
  liyijie d92233c9f2 ComPDFKit.Tool(win)-补充框选刷新事件 hace 3 meses
  liyijie 945ed28f60 ComPDFKit.Tool(win) - 补充undo redo 结束编辑模式逻辑,防止undoredo失效 hace 4 meses
  liyijie 2594b2389d ComPDFKit.Tool(win) - 框选补充隐藏逻辑 hace 4 meses
  liyijie 2aa1d909fa ComPDFKit.Tool(win)-框选取消逻辑优化,对齐逻辑优化,多选增加刷新渲染逻辑 hace 4 meses
  liyijie bdd760f0ff ComPDFKit.Tool(win)- 修复undo栈删除失败问题:导致注释无法删除 hace 4 meses
  liyijie 007e172d9a ComPDFKit.Tool(win)-优化对齐逻辑减少误差 hace 4 meses
  liyijie 90311abe02 ComPDFKit.Tool(win)-原点拖拽点拖拽范围优化 hace 4 meses
  liyijie 0c32ac9da8 ComPDFKit.Tool(win)-补充注释 hace 4 meses
  liyijie e38ca26381 ComPDFKit.Tool(win)-获取多选框移动距离 hace 4 meses
  liyijie 17a56b7809 ComPDFKit.Tool(win)-(补充:撤回上条记录)多选移动补充移动距离接口,优化移动精度 hace 4 meses
  liyijie 04de093e2a Revert "其他- 多选移动逻辑优化" hace 4 meses
  liyijie b6fa3536cd 其他- 多选移动逻辑优化 hace 4 meses
  TangJinZhou a2dabd9896 ComPDFKit.Tool(win) - 修复测量注释没刷新的问题 hace 4 meses
  liyijie 353810112e ComPDFKit.Tool(win)-事件补加空处理 hace 4 meses
  liyijie baf5ab430f Merge branch 'compdfkit_demo_win_dev' of http://git.kdan.cc:8865/Others/kmpdfkit_demo into compdfkit_demo_win_dev hace 4 meses
  liyijie 60c81ce6b7 ComPDFKit.Tool(win)-多选移动补充缩放比,多选拖拽补充鼠标样式逻辑 hace 4 meses
  TangJinZhou 6669f6208d ComPDFKit.Demo(win) - 修正IsMeasured接口名 hace 4 meses
  TangJinZhou f28f88f4e5 ComPDFKit.Tool(win) - 修正IsMeasured接口名 hace 4 meses
  liyijie e941b86992 ComPDFKit.Tool(win) - 优化裁剪在不同缩放比逻辑 hace 4 meses
  liyijie f154e056a5 ComPDFKit.Tool(win)-优化添加文字框显示逻辑 hace 4 meses
  liyuxuan 4a2b736adb ComPDFKit.Tool(win)-去掉中文注释 hace 4 meses
  liyuxuan 09e8bbe1e0 ComPDFKit.Tool(win)-优先判断选中状态的框 hace 4 meses
  liyijie 7107c381b3 ComPDFKit.Tool(win)-多选逻辑判断条件更改 hace 4 meses
  TangJinZhou cfcbad5093 ComPDFKit.Tool(win) - 处理内容编辑多选Undo问题 hace 4 meses
  TangJinZhou 45f6851836 ComPDFKit.Tool(win) - 优化if判断逻辑 hace 4 meses
  TangJinZhou 5bc7df189a ComPDFKit.Tool(win) - 优化内容编辑删除文字EndEdit逻辑 hace 4 meses
  TangJinZhou 83b001591a ComPDFKit.Tool(win) - 处理内容编辑删除文字块时Undo次数不对的问题 hace 4 meses
  liyijie 51a25f3caf ComPDFKit.Tool(win)-多选移动逻辑优化 hace 4 meses
  liyijie 10ded71552 ComPDFKit.Tool(win)-补充设置选中矩形可以拖至页面区域外逻辑 hace 4 meses
  liyuxuan 1ef494bdaa ComPDFKit.Tool(win)-修复文字编辑多选对齐操作后Undo再执行对齐操作位置不正确问题 hace 4 meses
  liyijie a98e6681db ComPDFKit.Tool(win)-批量删除逻辑优化,按注释索引高先删 hace 4 meses
  liyijie 69726c223f ComPDFKit.Tool(win)-优化多选移动逻辑 hace 4 meses
  liyuxuan bebceb784a ComPDFKit.Tool(win)-分组Undo Redo 对象Check函数更改 hace 4 meses
  liyijie 91036592b3 ComPDFKit.Tool(win)-其他配置文件回滚 hace 4 meses
  liyijie c55688ada7 Merge branch 'compdfkit_demo_win_dev' of http://git.kdan.cc:8865/Others/kmpdfkit_demo into compdfkit_demo_win_dev hace 4 meses
  liyijie 2492ca54de ComPDFKit.Tool(win)-补充光标移动事件,App获取当前光标对象更新属性面板 hace 4 meses
  liyuxuan 331de55823 ComPDFKit.Tool(win)-修改批量删除Undo Redo 问题,和修复删除中间注释后Undo Redo 异常问题 hace 4 meses
  liyijie b336950ccb ComPDFKit.Tool(win)-多选减少事件更新,多选拖动更改图片对象获取矩形逻辑防止拖拽异常变大 hace 4 meses
  liyijie 7b4c4de904 ComPDFKit.Tool(win)-补充设置添加内容编辑的鼠标 hace 4 meses
  liyijie 009a4a1cbd ComPDFKit.Tool(win)-多选删除当前选中矩形 hace 4 meses
  liyijie ac15af82c5 Merge branch 'compdfkit_demo_win_dev' of http://git.kdan.cc:8865/Others/kmpdfkit_demo into compdfkit_demo_win_dev hace 4 meses
  liyijie db11bd4422 ComPDFKit.Tool(win)-调整裁剪参数(矩形改为间距) hace 4 meses
  TangJinZhou c242fc407f Merge remote-tracking branch 'origin/compdfkit_demo_win_dev' into compdfkit_demo_win_dev hace 4 meses
  TangJinZhou 6493ef495c ComPDFKit.Tool(win) - 还原版本号 hace 4 meses
  liyijie 23f0bb94fd ComPDFKit.Tool(win)-创建文字颜色判断条件优化 hace 4 meses
  liyijie ab999da377 Merge branch 'compdfkit_demo_win_dev' of http://git.kdan.cc:8865/Others/kmpdfkit_demo into compdfkit_demo_win_dev hace 4 meses
  liyijie 26c7744912 ComPDFKit.Tool(win)-补充是否连续创建文字编辑逻辑 hace 4 meses
  TangJinZhou c1f341a183 ComPDFKit.Tool(win) - 更新版本号 hace 4 meses
  liuaoran 114d29194d ComPDFKit.Demo(win) - 子集化开关 hace 4 meses
  liuaoran 495102cd0b ComPDFKit.Tools/.Demo - 设置是否显示文本块/文本块移出屏幕后输入崩溃判空 hace 4 meses
  liyijie bc8d0d3e3d ComPDFKit.Tool(win)-补充多选悬浮鼠标变化 hace 4 meses
  liyijie 1a00c26379 ComPDFKit.Tool(win)-补充设置绘画参数,优化移动框绘制逻辑,补充绘制移动边框画笔 hace 4 meses
  liyijie e90448de79 ComPDFKit.Tool(win)-回滚配置文件代码 hace 4 meses
  liyijie 0c5ae0552b Merge branch 'compdfkit_demo_win_dev' of http://git.kdan.cc:8865/Others/kmpdfkit_demo into compdfkit_demo_win_dev hace 4 meses
  liyijie 67def0f985 ComPDFKit.Tool(win)-编辑悬浮颜色调整 hace 4 meses
  TangJinZhou edd6fb44de ComPDFKit.Demo(win) - 处理缩略图控件绑定失败的问题 hace 4 meses
  TangJinZhou e1157481b1 ComPDFKit.Demo(win) - 处理PDFViewer关闭多页签时CPDFDocument没释放的问题 hace 4 meses
  TangJinZhou 09a9b25b13 ComPDFKit.Tool(win) - 修复文字搜索密码错误或页面范围错误时Crash的问题 hace 4 meses
  TangJinZhou 88400cf4a5 ComPDFKit.Tool(win) - 优化加密文档搜索验证密码逻辑 hace 4 meses
  TangJinZhou 1e75e07976 ComPDFKit.Tool(win) - 调整代码规范 hace 4 meses
  youna b6871f9d6e ComPDFKit.Demo(win) - 修复密码文档无法搜索问题 hace 4 meses
  liyijie 83c543ed76 ComPDFKit.Tool(win)-去掉中文注释和无效代码 hace 4 meses
  liyijie 3b88ad8e2f Merge branch 'compdfkit_demo_win_dev' of http://git.kdan.cc:8865/Others/kmpdfkit_demo into compdfkit_demo_win_dev hace 4 meses
  liyijie 2d85901cd6 ComPDFKit.Tolol(win)-水平平分和垂直平分逻辑优化 hace 4 meses
  youna ac761e64c3 ComPDFKit.Control(win) - 内容编辑添加多选模式开关 hace 4 meses
  youna cfc2077b42 ComPDFKit.Tool(win) - 补充获取当前是否多选状态的接口 hace 4 meses
  liyijie 3b0c541bcd ComPDFKit.Tool(win)-接口名字调整 hace 4 meses
  liyijie 5b03343653 Merge branch 'compdfkit_demo_win_dev' of http://git.kdan.cc:8865/Others/kmpdfkit_demo into compdfkit_demo_win_dev hace 4 meses
  liyijie 142cec2c93 ComPDFKit.Tool(win)-补充内容编辑UX改版接口 hace 4 meses
  TangJinZhou b63246844f ComPDFKit.Tool(win) - 修复在刷新注释时会重现渲染页面的问题 hace 4 meses
  youna a4db688ddf ComPDFKit.Demo(win) - 注释回复 Converter hace 4 meses
  youna ef8cbdba28 ComPDFKit.Demo(win) - 注释回复 hace 4 meses
  liyijie 75c7e5b180 ComPDFKit.Tool(win)-图片裁剪框处理逻辑,部分多选数据处理,框选逻辑,内容对齐逻辑,图片的悬浮,裁剪确认逻辑 hace 4 meses
  liyijie f9e9a592ce ComPDFKit.Tool(win)-APP多选获取数据,数据储存,鼠标获取裁剪框的裁剪区域位置 hace 4 meses
  liyijie 2f712ae053 ComPDFKit.Tool(win)-添加多选入口,框选方法初始化,图片裁剪框初始化 hace 4 meses
  liyijie d7c0690657 ComPDFKit.Tool(win)-多选数据的处理,开启多选和关闭多选逻辑调整 hace 4 meses
  liyijie 80634de3c9 ComPDFKit.Tool(win)-补充多选的复制粘贴裁剪删除逻辑 hace 4 meses
  liyijie 713399f6ee ComPDFKit.Tool(win)-多选样式,框选辅助工具 hace 4 meses
  liyijie 4a5c929d0c compdfkit(win)-编辑单选框样式调整为(文字两原点)(图片六原点),裁剪获取边框点范围,获取以及设置当前裁剪框,调整编辑初步显示样式,绘制单选选中辅助线 hace 4 meses
  liyijie 8d8fa1ea89 compdfkit(win)-换库参数调整 hace 4 meses
  liuaoran bdf6441f4b compdfkit(win) - 更改右侧面板icon,添加表单和显示滑动条自动显示 hace 4 meses
  liuaoran 3a622e7aa7 compdfkit(win) - 内容编辑,窗口过小时属性面板滑动条 hace 4 meses
  youna 661ec0f2ff compdfkit(win) - 打印翻页样式补充 hace 4 meses
  youna 64572a3a39 compdfkit(win) - 缓存 hace 4 meses
  youna 6575af4154 compdfkit(win) - 设置页 hace 4 meses
  youna 2c29b5283c compdfkit(win) - 打印文案&注释回复文案 hace 4 meses
  TangJinZhou b9555cf244 ComPDFKit.Demo(win) - 修正字体管理接口名称 hace 5 meses
  TangJinZhou d2df6f7235 ComPDFKit(win) - 修正字体管理接口名称 hace 5 meses
  TangJinZhou 49915fe407 ComPDFKit.Demo(win) - 处理内容编辑快捷键重复设置Rect的问题 hace 5 meses
  TangJinZhou 8bb4834837 ComPDFKit.Demo(win) - 处理数字签名模块点击签名域无法添加签名的问题 hace 5 meses
  TangJinZhou c3a138c036 Merge remote-tracking branch 'origin/compdfkit_demo_win_rebuild' into compdfkit_demo_win_dev hace 5 meses
  youna 6191bc4a47 ComPDFKit(win) - 打印 hace 5 meses
Se han modificado 100 ficheros con 9492 adiciones y 2061 borrados
  1. 1 1
      Demo/Examples/Annotations/MainWindow.xaml
  2. 2 2
      Demo/Examples/Annotations/Properties/AssemblyInfo.cs
  3. 139 1
      Demo/Examples/ComPDFKit.Tool/AlignmentsHelp.cs
  4. 444 81
      Demo/Examples/ComPDFKit.Tool/CPDFToolManager.cs
  5. 38 13
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.Annot.cs
  6. 1136 0
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.AnnotSelector.cs
  7. 161 18
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.Command.cs
  8. 2 0
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.CustomizeTool.cs
  9. 29 30
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.DataMethod.cs
  10. 6 0
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.FindReplace.cs
  11. 108 37
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.MultiSelectedRect.cs
  12. 131 0
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.PDFCompareEffect.cs
  13. 35 7
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.SelectImage.cs
  14. 4 1
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.SelectText.cs
  15. 17 1
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.SelectedRect.cs
  16. 1196 59
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.TextEdit.cs
  17. 10 0
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.WidgetTool.cs
  18. 2 4
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.xaml
  19. 232 26
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.xaml.cs
  20. 26 1
      Demo/Examples/ComPDFKit.Tool/ComPDFKit.Tool.csproj
  21. 195 116
      Demo/Examples/ComPDFKit.Tool/DrawTool/AnnotEdit.cs
  22. 210 0
      Demo/Examples/ComPDFKit.Tool/DrawTool/AnnotSelector.cs
  23. 61 18
      Demo/Examples/ComPDFKit.Tool/DrawTool/CreateAnnotTool.cs
  24. 16 1
      Demo/Examples/ComPDFKit.Tool/DrawTool/CreateCustomizeTool.cs
  25. 47 0
      Demo/Examples/ComPDFKit.Tool/DrawTool/DashBorder.cs
  26. 450 0
      Demo/Examples/ComPDFKit.Tool/DrawTool/FrameSelectTool.cs
  27. 193 17
      Demo/Examples/ComPDFKit.Tool/DrawTool/MultiSelectedRect.cs
  28. 301 19
      Demo/Examples/ComPDFKit.Tool/DrawTool/SelectedRect.cs
  29. 404 23
      Demo/Examples/ComPDFKit.Tool/DrawTool/SelectedRect.protected.cs
  30. 83 0
      Demo/Examples/ComPDFKit.Tool/Help/CommonHelper.cs
  31. 20 1
      Demo/Examples/ComPDFKit.Tool/Help/PDFHelp.cs
  32. 87 9
      Demo/Examples/ComPDFKit.Tool/Help/ParamConverter.cs
  33. 70 81
      Demo/Examples/ComPDFKit.Tool/PDFTextSearch.cs
  34. 9 1
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/FreeTextParam.cs
  35. 9 2
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/InkParam.cs
  36. 23 18
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/LineMeasureParam.cs
  37. 5 1
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/StampParam.cs
  38. 3 0
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/StickyNoteParam.cs
  39. 18 0
      Demo/Examples/ComPDFKit.Tool/SettingParam/DefaultSettingParam.cs
  40. 2 2
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory.cs
  41. 18 26
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/FreeTextAnnotHistory.cs
  42. 15 0
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/InkAnnotHistory.cs
  43. 14 10
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/LineMeasureAnnotHistory.cs
  44. 1 1
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/PolyLineMeasureAnnotHistory.cs
  45. 1 1
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/PolygonMeasureAnnotHistory.cs
  46. 242 9
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/StampAnnotHistory.cs
  47. 13 2
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/StickyNoteAnnotHistory.cs
  48. 4 28
      Demo/Examples/ComPDFKit.Tool/UndoManger/FormHistory/ComboBoxHistory.cs
  49. 4 29
      Demo/Examples/ComPDFKit.Tool/UndoManger/FormHistory/ListBoxHistory.cs
  50. 4 28
      Demo/Examples/ComPDFKit.Tool/UndoManger/FormHistory/PushButtonHistory.cs
  51. 4 28
      Demo/Examples/ComPDFKit.Tool/UndoManger/FormHistory/TextBoxHistory.cs
  52. 8 7
      Demo/Examples/ComPDFKit.Tool/UndoManger/GroupHistory.cs
  53. 1 1
      Demo/Examples/ComPDFKit.Tool/UndoManger/MultiAnnotHistory.cs
  54. 28 21
      Demo/Examples/ComPDFKit.Tool/UndoManger/PDFEditHistory/PDFEditHistory.cs
  55. 1 1
      Demo/Examples/Compdfkit.Controls/Annotation/CPDFAnnotationPreviewerControl.xaml.cs
  56. 6 1
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationData/CPDFAnnotationData.cs
  57. 65 1
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListControl/CPDFAnnotationListControl.xaml
  58. 203 18
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListControl/CPDFAnnotationListControl.xaml.cs
  59. 134 0
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/AnnotationReplyListControl.xaml
  60. 215 0
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/AnnotationReplyListControl.xaml.cs
  61. 0 239
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/CPDFAnnoationListUI.xaml.cs
  62. 121 24
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/CPDFAnnoationListUI.xaml
  63. 690 0
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/CPDFAnnotationListUI.xaml.cs
  64. 71 0
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/ReplyStatusControl.xaml
  65. 175 0
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/ReplyStatusControl.xaml.cs
  66. 8 4
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationControl/CPDFAnnotationControl.xaml.cs
  67. 1 0
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationUI/CPDFSignatureUI.xaml.cs
  68. 1 1
      Demo/Examples/Compdfkit.Controls/Asset/Styles/ComboBoxStyle.xaml
  69. 0 2
      Demo/Examples/Compdfkit.Controls/Asset/Styles/ListBoxItemStyle.xaml
  70. 4 0
      Demo/Examples/Compdfkit.Controls/Common/BarControl/CPDFTitleBarControl.xaml
  71. 7 1
      Demo/Examples/Compdfkit.Controls/Common/BarControl/CPDFTitleBarControl.xaml.cs
  72. 2 4
      Demo/Examples/Compdfkit.Controls/Common/BaseControl/PageNumberControl.xaml
  73. 3 3
      Demo/Examples/Compdfkit.Controls/Common/Convert/AnnotArgsTypeToVisibilityConverter.cs
  74. 25 0
      Demo/Examples/Compdfkit.Controls/Common/Convert/AntiVisibilityConverter.cs
  75. 8 10
      Demo/Examples/Compdfkit.Controls/Common/Convert/LanguageResourceConverter.cs
  76. 28 0
      Demo/Examples/Compdfkit.Controls/Common/Convert/SubtractionConverter.cs
  77. 1 1
      Demo/Examples/Compdfkit.Controls/Common/PropertyControl/PDFFont/CPDFFontControl.xaml.cs
  78. 48 7
      Demo/Examples/Compdfkit.Controls/Compdfkit.Controls.csproj
  79. 3 1
      Demo/Examples/Compdfkit.Controls/DigitalSignature/DigitalSignatureControl/DigitalSignatureControl.xaml.cs
  80. 102 36
      Demo/Examples/Compdfkit.Controls/Edit/ContentEditCOntrol/ContentEditControl.xaml.cs
  81. 4 2
      Demo/Examples/Compdfkit.Controls/Edit/PDFContentEditControl.xaml.cs
  82. 90 96
      Demo/Examples/Compdfkit.Controls/Edit/PDFImageEdit/PDFImageEditControl/PDFImageEditControl.xaml
  83. 267 140
      Demo/Examples/Compdfkit.Controls/Edit/PDFImageEdit/PDFImageEditControl/PDFImageEditControl.xaml.cs
  84. 53 44
      Demo/Examples/Compdfkit.Controls/Edit/PDFTextEdit/PDFTextEditControl/PDFTextEditControl.xaml
  85. 360 151
      Demo/Examples/Compdfkit.Controls/Edit/PDFTextEdit/PDFTextEditControl/PDFTextEditControl.xaml.cs
  86. 80 77
      Demo/Examples/Compdfkit.Controls/Form/Property/CheckBoxProperty.xaml
  87. 104 101
      Demo/Examples/Compdfkit.Controls/Form/Property/ComboBoxProperty.xaml
  88. 1 1
      Demo/Examples/Compdfkit.Controls/Form/Property/ComboBoxProperty.xaml.cs
  89. 104 101
      Demo/Examples/Compdfkit.Controls/Form/Property/ListBoxProperty.xaml
  90. 1 1
      Demo/Examples/Compdfkit.Controls/Form/Property/ListBoxProperty.xaml.cs
  91. 90 88
      Demo/Examples/Compdfkit.Controls/Form/Property/PushButtonProperty.xaml
  92. 1 1
      Demo/Examples/Compdfkit.Controls/Form/Property/PushButtonProperty.xaml.cs
  93. 3 1
      Demo/Examples/Compdfkit.Controls/Form/Property/RadioButtonProperty.xaml
  94. 29 26
      Demo/Examples/Compdfkit.Controls/Form/Property/SignatureProperty.xaml
  95. 91 88
      Demo/Examples/Compdfkit.Controls/Form/Property/TextFieldProperty.xaml
  96. 1 1
      Demo/Examples/Compdfkit.Controls/Form/Property/TextFieldProperty.xaml.cs
  97. 2 2
      Demo/Examples/Compdfkit.Controls/Measure/MeasureControl.xaml.cs
  98. 3 3
      Demo/Examples/Compdfkit.Controls/Measure/MeasureSettingPanel.xaml.cs
  99. 4 1
      Demo/Examples/Compdfkit.Controls/PDFView/PDFDisplaySettings/PDFDisplaySettingsControl/CPDFDisplaySettingsControl.xaml
  100. 0 0
      Demo/Examples/Compdfkit.Controls/PDFView/PDFSearch/PDFSearchControl/CPDFSearchControl.xaml.cs

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

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

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

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

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

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

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

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

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

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

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1136 - 0
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.AnnotSelector.cs


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1196 - 59
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.TextEdit.cs


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 65 - 1
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListControl/CPDFAnnotationListControl.xaml


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

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

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

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

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

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

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

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

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 121 - 24
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/CPDFAnnoationListUI.xaml


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

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

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

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

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 175 - 0
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/ReplyStatusControl.xaml.cs


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+
+namespace ComPDFKit.Controls.Common 
+{
+    [ValueConversion(typeof(double), typeof(double))]
+    public class SubtractionConverter : IValueConverter
+    {
+        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (value is double actualWidth && parameter is string parameterValue && double.TryParse(parameterValue, out double subtractValue))
+            {
+                return actualWidth - subtractValue;
+            }
+            return value;
+        }
+
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            return null;
+        }
+    }
+}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 104 - 101
Demo/Examples/Compdfkit.Controls/Form/Property/ComboBoxProperty.xaml


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

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

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 104 - 101
Demo/Examples/Compdfkit.Controls/Form/Property/ListBoxProperty.xaml


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio