实现效果:

问题点:Adobe PDF Reader中并没有可以直接旋转的方法

LoadFile 加载文件,文件URL地址
GotoFirstPage 到第一页
GotoLastPage 到最后一页
GotoPreviousPage 上一页
GotoNextPape 下一页
SetCurrentpage 到指定页
Setshowscrollbars 设置是否显示 Acrobat Reader的滚动条。带一个参数,该参数设为0时不显示滚动条,设为1时显示滚动条
SetshowToolbar 设置是否显示 Acrobat Reader的工具栏。带一个参数,该参数设为时不显示,设为1时显示。
Setview 设置显示效果。Fit:适应窗口大小; FitH:适合宽度
setZoom 设置文件的显示比例;默认是100

解决办法:引入PdfiumViewer旋转PDF并保存替换当前的文件。

		 /// <summary>
/// 旋转保存PDF文件并释放文件锁定
/// </summary>
/// <param name="axControl"></param>
/// <param name="filePath"></param>
/// <param name="pdfRotation"></param>
/// <returns></returns>
public bool SafeSavePdfWithRelease(AxAcroPDFLib.AxAcroPDF axControl, string filePath, PdfRotation pdfRotation)
{
const int MAX_RETRY = 3;
const int RETRY_DELAY = 500; for (int attempt = 0; attempt < MAX_RETRY; attempt++)
{
try
{
// 步骤1:创建临时副本
string tempPath = Path.GetTempFileName().Replace(".tmp", ".pdf");
File.Copy(filePath, tempPath, true); // 步骤2:使用内存流操作
using (var ms = new MemoryStream(File.ReadAllBytes(tempPath)))
using (var document = PdfiumViewer.PdfDocument.Load(ms))
{
for (int pageIndex = 0; pageIndex < document.PageCount; pageIndex++)
{
document.RotatePage(pageIndex, pdfRotation); // 可选:验证旋转结果
// var currentRotation = document.Pages[pageIndex].Rotation;
// Debug.Assert(currentRotation == (int)rotation);
}
// 执行修改操作(示例:旋转第一页)
//document.RotatePage(1, PdfRotation.Rotate90); // 步骤3:保存到临时文件
byte[] pdfBytes;
using (var outputStream = new MemoryStream())
{
document.Save(outputStream);
pdfBytes = outputStream.ToArray();
} // 步骤4:强制释放文件锁定
ForceReleasePdfFile(axControl, filePath); // 步骤5:原子替换文件
File.WriteAllBytes(tempPath, pdfBytes);
// File.Replace(tempPath, filePath, null, true); // 1. 复制替换文件到目标路径
File.Copy(tempPath, filePath, overwrite: true); // 2. 删除临时文件(可选)
File.Delete(tempPath); // 步骤6:验证加载
axControl.LoadFile(filePath);
return true;
}
}
catch (IOException ex) when (ex.HResult == -2147024864)
{
if (attempt == MAX_RETRY - 1) throw;
Thread.Sleep(RETRY_DELAY);
}
}
return false;
}
public void ForceReleasePdfFile(AxAcroPDFLib.AxAcroPDF axControl, string filePath)
{
// 步骤1:深度释放COM对象
ReleaseComObject(axControl); // 步骤2:内核级文件解锁
UnlockFileHandle(filePath); // 步骤3:延迟重载验证
Thread.Sleep(200);
axControl.LoadFile(filePath);
} private void ReleaseComObject(AxAcroPDFLib.AxAcroPDF axControl)
{
try
{
// 显式释放ActiveX资源
if (axControl.IsDisposed) return; // 反射调用内部释放方法
var type = axControl.GetType();
var method = type.GetMethod("ReleaseOCX", BindingFlags.Instance | BindingFlags.NonPublic);
method?.Invoke(axControl, null); // 强制垃圾回收
GC.Collect();
GC.WaitForPendingFinalizers();
}
catch (Exception ex)
{ }
}
// 修改后的P/Invoke声明
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
FileMode dwCreationDisposition, // 改用.NET枚举
FileAttributes dwFlagsAndAttributes, // 改用.NET枚举
IntPtr hTemplateFile); // 修改后的UnlockFileHandle方法
private void UnlockFileHandle(string filePath)
{
const uint FILE_SHARE_READ = 0x00000001;
const uint FILE_SHARE_WRITE = 0x00000002;
const uint GENERIC_READ = 0x80000000; IntPtr hFile = CreateFile(
filePath,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
IntPtr.Zero,
FileMode.Open, // 对应原生OPEN_EXISTING
FileAttributes.Normal, // 对应原生FILE_ATTRIBUTE_NORMAL
IntPtr.Zero); if (hFile != IntPtr.Zero && hFile != new IntPtr(-1))
{
CloseHandle(hFile);
}
} [DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);`

调用代码:

		  /// <summary>
/// 当前旋转角度
/// </summary>
public static int currentRotation = 0; /// <summary>
/// 逆时针旋转
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void pictureEdit3_Click(object sender, EventArgs e)
{
if (axAcroPDF1.Visible)
{
currentRotation -= 90; PdfRotation pdfRotation = GetCounterClockwiseRotation(currentRotation); var path = axAcroPDF1.src;
//调用旋转PDF保存方法
SafeSavePdfWithRelease(axAcroPDF1, path,pdfRotation);
axAcroPDF1.LoadFile(path);
axAcroPDF1.setView("Fit"); //适应窗口大小
}
} /// <summary>
/// 顺时针旋转
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void pictureEdit2_Click(object sender, EventArgs e)
{
if (axAcroPDF1.Visible)
{
currentRotation += 90; PdfRotation pdfRotation = GetCounterClockwiseRotation(currentRotation); var path = axAcroPDF1.src;
//调用旋转PDF保存方法
SafeSavePdfWithRelease(axAcroPDF1, path, pdfRotation); axAcroPDF1.LoadFile(path);
axAcroPDF1.setView("Fit"); //适应窗口大小
}
} /// <summary>
/// 通过旋转度数计算旋转的角度
/// </summary>
/// <param name="counterClockwiseDegrees">当前旋转角度</param>
public static PdfRotation GetCounterClockwiseRotation(int counterClockwiseDegrees)
{
const int fullCircle = 360;
int effectiveDegrees = counterClockwiseDegrees % fullCircle; if (effectiveDegrees < 0) effectiveDegrees += fullCircle; // 处理负角度 if (currentRotation >= 360)
{
currentRotation = 0;
}
if (currentRotation <= -360)
{
currentRotation = 0;
} switch (effectiveDegrees)
{
case 90:
return PdfRotation.Rotate90;
case 180:
return PdfRotation.Rotate180;
case 270:
return PdfRotation.Rotate270;
case 0:
default:
return PdfRotation.Rotate0;
}
}
/// <summary>

WinForms中实现Adobe PDF Reader实现旋转PDF功能的更多相关文章

  1. PDF怎么编辑,如何旋转PDF页面方向

    很多的时候,无论是工作中,还是在学习中都会遇到PDF文件,对于PDF文件,熟悉的小伙伴知道,在编辑PDF文件的时候,是需要使用到PDF编辑软件的,那么,在编辑PDF文件的时候,需要旋转文件的页面,这时 ...

  2. Adobe Acrobat Reader DC 离线安装包

    https://blog.csdn.net/qqduxingzhe/article/details/77876336 ************************************* win ...

  3. 怎样用Adobe Acrobat 7 Pro把PDF文档拆分成多个啊?

    这个pdf文档里有多篇文章,我想把他们分开并分别保存在独立的pdf文档.怎么操作?我的电脑基础不太好,麻烦说得详细一些. Adobe Acrobat 7 Pro拆分PDF文档的方法: 1.点左边的“书 ...

  4. 使用Adobe Arcobat Pro DC生成PDF提示“PDFMaker文件遗失”新解决思路

    环境: 1.Window 7 2.Adobe Arcobat Pro DC 2020.009.20065 3.Microsoft Office 2007 4.WPS 2019 虽然可以使用插件实现文件 ...

  5. python实现PDF指定页面旋转

    下面示例代码,是将横向纸张旋转为纵向(根据纸张大小判断纸张方向) 方法一:使用PyPDF2库 from PyPDF2 import PdfFileWriter, PdfFileReader def p ...

  6. 如何使用免费PDF控件从PDF文档中提取文本和图片

             如何使用免费PDF控件从PDF文档中提取文本和图片 概要 现在手头的项目有一个需求是从PDF文档中提取文本和图片,我以前也使用过像iTextSharp, PDFBox 这些免费的PD ...

  7. 将Altium中的原理图与PCB导出为PDF的步骤与方法

    1.通过File-Smart PDF(文件-智能PDF),快捷键F-M打开. 2.选择打印的范围:Current Project还是Current Document,还有生成的PDF的存放位置. 3. ...

  8. Foxit Reader(福昕PDF阅读器) v4.3.1.218 绿色专业版

    软件名称:Foxit Reader(福昕PDF阅读器) v4.3.1.218 绿色专业版 软件语言: 简体中文 授权方式: 免费软件 运行环境: Win 32位/64位 软件大小: 4.40MB 图片 ...

  9. PDF中的空白页面怎么删除,PDF页面删除技巧

    在Word中想要删除其中一页文档的怎么办?直接打开就可以删除了,那么我们如何删除PDF其中几页呢?下面小编就来告诉大家PDF删除页面跟空白页面的方法.想要删除PDF文档中的页面,可以使用PDF编辑器, ...

  10. 官网下载到离线的Adobe Acrobat Reader DC

    Adobe 官方 FTP :ftp://ftp.adobe.com/ Adobe Acrobat Reader DC 下载目录:ftp://ftp.adobe.com/pub/adobe/reader ...

随机推荐

  1. BUUCTF---达芬奇的密码

    题目 达芬奇隐藏在蒙娜丽莎中的数字列:1 233 3 2584 1346269 144 5 196418 21 1597 610 377 10946 89 514229 987 8 55 6765 2 ...

  2. 什么是 MCP,以及你为什么该关注它

    MCP 现在真的火起来了.现在已经有成千上万个 MCP "服务器",而且虽然是 Anthropic 发明的,就在几天前 OpenAI 也采纳了它.服务器就像 AI 的 " ...

  3. Linux终端居然也可以做文件浏览器?

    大家好,我是良许. 在抖音上做直播已经整整 5 个月了,我很自豪我一路坚持到了现在[笑脸] 最近我在做直播的时候,也开始学习鱼皮大佬,直播写代码.当然我不懂 Java 后端,因此就写写自己擅长的 Sh ...

  4. Kylin-Server-V10-SP3物理机安装简要过程

    1.下载镜像 链接: https://eco.kylinos.cn/partners/mirror.html?class_id=1&query_key=V10 选择: 银河麒麟高级服务器操作系 ...

  5. Springboot连接Greenplum,分页查询

    1.springboot分页查询greenplum数据报错: org.mybatis.spring.MyBatisSystemException: nested exception is org.ap ...

  6. Cobalt Strike基础

    Cobalt Strike基础 Staged(有阶段) 在有阶段的执行方式中,分为Stager和Stage两个阶段 Stager(初始执行载荷): ​ 定义:Stager是Stage 1,是一个较小的 ...

  7. MySQL 的覆盖索引是什么?

    MySQL 的覆盖索引是什么? 覆盖索引(Covering Index)是指索引本身包含了查询所需的所有字段数据,从而无需再回表查询的数据访问方式.这种优化能够显著提升查询性能. 1. 覆盖索引的特点 ...

  8. GC垃圾收集时,居然还有用户线程在奔跑

    之前面试被问到过"当GC垃圾收集时,是所有的用户线程都停止了吗?",这一篇我们来探究一下这个问题. 其实执行本地代码的线程仍然可以运行,那么这些线程一旦改变了对象中的引用关系或创建 ...

  9. Maven依赖冲突解决方案:调解规则与工具实践

    结论先行 Maven解决依赖冲突的核心机制是 依赖调解 和 显式排除 ,并通过插件(如maven-dependency-plugin.maven-enforcer-plugin和Maven Helpe ...

  10. 记录一次mysql数据库修复过程

    1. 场景 最近在使用小皮面板进行靶场搭建的时候,发现数据库一直无法启动,而在虚拟机里是可以启动了,这就很奇怪了.意识到我的本地已经安装了mysql,可能产生了冲突,但是当我兴冲冲启动本地mysql的 ...