WinForms中实现Adobe PDF Reader实现旋转PDF功能
实现效果:
问题点: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功能的更多相关文章
- PDF怎么编辑,如何旋转PDF页面方向
很多的时候,无论是工作中,还是在学习中都会遇到PDF文件,对于PDF文件,熟悉的小伙伴知道,在编辑PDF文件的时候,是需要使用到PDF编辑软件的,那么,在编辑PDF文件的时候,需要旋转文件的页面,这时 ...
- Adobe Acrobat Reader DC 离线安装包
https://blog.csdn.net/qqduxingzhe/article/details/77876336 ************************************* win ...
- 怎样用Adobe Acrobat 7 Pro把PDF文档拆分成多个啊?
这个pdf文档里有多篇文章,我想把他们分开并分别保存在独立的pdf文档.怎么操作?我的电脑基础不太好,麻烦说得详细一些. Adobe Acrobat 7 Pro拆分PDF文档的方法: 1.点左边的“书 ...
- 使用Adobe Arcobat Pro DC生成PDF提示“PDFMaker文件遗失”新解决思路
环境: 1.Window 7 2.Adobe Arcobat Pro DC 2020.009.20065 3.Microsoft Office 2007 4.WPS 2019 虽然可以使用插件实现文件 ...
- python实现PDF指定页面旋转
下面示例代码,是将横向纸张旋转为纵向(根据纸张大小判断纸张方向) 方法一:使用PyPDF2库 from PyPDF2 import PdfFileWriter, PdfFileReader def p ...
- 如何使用免费PDF控件从PDF文档中提取文本和图片
如何使用免费PDF控件从PDF文档中提取文本和图片 概要 现在手头的项目有一个需求是从PDF文档中提取文本和图片,我以前也使用过像iTextSharp, PDFBox 这些免费的PD ...
- 将Altium中的原理图与PCB导出为PDF的步骤与方法
1.通过File-Smart PDF(文件-智能PDF),快捷键F-M打开. 2.选择打印的范围:Current Project还是Current Document,还有生成的PDF的存放位置. 3. ...
- Foxit Reader(福昕PDF阅读器) v4.3.1.218 绿色专业版
软件名称:Foxit Reader(福昕PDF阅读器) v4.3.1.218 绿色专业版 软件语言: 简体中文 授权方式: 免费软件 运行环境: Win 32位/64位 软件大小: 4.40MB 图片 ...
- PDF中的空白页面怎么删除,PDF页面删除技巧
在Word中想要删除其中一页文档的怎么办?直接打开就可以删除了,那么我们如何删除PDF其中几页呢?下面小编就来告诉大家PDF删除页面跟空白页面的方法.想要删除PDF文档中的页面,可以使用PDF编辑器, ...
- 官网下载到离线的Adobe Acrobat Reader DC
Adobe 官方 FTP :ftp://ftp.adobe.com/ Adobe Acrobat Reader DC 下载目录:ftp://ftp.adobe.com/pub/adobe/reader ...
随机推荐
- mac环境配置本地nfs服务
前言 在这篇文章中,讲了在Mac端开启NFS服务,并通过NFS协议让其他设备挂载到你的Mac上. 步骤一:增加配置文件 首先,我们需要编辑NFS的配置文件,以便定义哪些目录可以被远程访问. 打开终端, ...
- Ubuntu22.04 搭建Kubernetes 1.28版本集群
依赖安装 准备工作需要在所有节点上进行. 安装 ssh 服务 安装 openssh-server sudo apt-get install openssh-server 修改配置文件 vim /etc ...
- 解决Linux下文本文件中文乱码问题
上一篇我们提到了OS和DB的一些中文乱码问题解决,本篇我们继续介绍下在OS上的文本文件中文乱码问题. 操作系统是Linux(OEL 8.10),所有文件是打了一个压缩包上传的,上传解压后发现其中的文本 ...
- 学习unigui【23】uniDBGrid的使用摘要
Unidbgrid自动调整列宽 UniDBGrid1 -> ClientEvents -> ExtEvents [Ext.data.Store[store] ] add store.loa ...
- 详细介绍Mybatis的缓存机制
一.缓存机制 1.缓存概述 缓存:缓存就是一块内存空间,保存临时数据 作用:将数据源(数据库或者文件)中的数据读取出来存放到缓存中,再次获取时直接从缓存中获取,可以减少和数据库交互的次数,提升程序的性 ...
- 如何应对ADAS/AD海量数据处理挑战?
随着软件定义汽车的发展,车辆生成的数据量也以前所未有的速度不断增加.这些数据包含广泛的信息,包括传感器数据.遥测数据.诊断数据等.在开发过程中,有效处理这些数据并从中获得见解至关重要. 对于原始设备制 ...
- 2024dsfzB层考试总结
2024B层次十一集训 10.3日 数据结构专题模拟 考试总结 FrankWKD Updated AT 2024/10/3 13:21 概述 总分:\(140/400\) Rank:\(24/87\) ...
- 微信小程序 6/12 的坑
配置 小程序的时候配置请求的是 https://xxx 不是http://xxx 前端请求的链接都是https
- 俩天完美复刻DeepWiki,并且免费开源!
俩天完美复刻DeepWiki,并且免费开源! 大家好!今天非常高兴为大家介绍KoalaWiki项目 - 这是我们团队花费两天时间完美复刻一个免费开源的AI驱动代码知识库系统,可以说是DeepWiki的 ...
- MIUI系统,APKMirror Installer安装apkm的时候提示app installation failed Installation aborted解决方案
场景 我的手机是MIUI系统,通过APKMirror Installer安装apkm的时候提示app installation failed Installation aborted. 本来不想装了, ...