施婉秀 发表于 2025-6-11 10:40:30

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.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声明
   
    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);
      }
    }

   
   
    private static extern bool CloseHandle(IntPtr hObject);`调用代码:
                  ///         /// 当前旋转角度      ///         public static int currentRotation = 0;      ///         /// 逆时针旋转      ///         ///         ///         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"); //适应窗口大小            }      }      ///         /// 顺时针旋转      ///         ///         ///         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"); //适应窗口大小             }      }      ///         /// 通过旋转度数计算旋转的角度      ///         /// 当前旋转角度      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
页: [1]
查看完整版本: WinForms中实现Adobe PDF Reader实现旋转PDF功能