C# 对PdfiumViewer工具栏进行自定义,实现放大缩小,首页, 尾页,上一页等功能。

文章目录

      • 前言
      • PdfiumViewer工具栏扩展
        • 1 创建winform工程,UI界面
        • 2 打印预览
        • 3 放大功能
        • 4 缩小功能
        • 5 按比例缩放
        • 6 全屏
        • 7 首页和尾页
        • 8 上一页和下一页
        • 9 页码输入框
        • 10 显示当前预览的页码
      • 小结

前言

关于PdfiumViewer的介绍 C# 使用PdfiumViewer实现对PDF文档打印预览(二),可以查看上一篇的文章。因为PdfiumViewer控件在工具栏展现的功能只有 保存、打印、放大、缩小这四个,现在想加上首页、尾页、上一页(下一页)的功能,以及显示当前页码,扩展一下功能。
在这里插入图片描述
改造成下面这个样子。
在这里插入图片描述

PdfiumViewer工具栏扩展

1 创建winform工程,UI界面

创建一个winform工程,在窗体上先放一个ToolStrip,再放置一个PdfiumViewer命名为pdfViewer1,将Dock属性设置为Full。
ToolStrip中从左到右控件的名称和对应的功能如下表:

控件类型控件名称描述
ToolStripButtonbtnPrint打印预览
ToolStripButtonbtnZomIn放大
ToolStripComboBoxcbZoomRate缩放比例
ToolStripButtonbtnZomOut缩小
ToolStripButtonbtnFullScreen全屏
ToolStripButtonbtnFirstPage首页
ToolStripButtonbtnPreviePage上一页
ToolStripTextBoxtbSetPage页码输入框
ToolStripLabellbTotalPage显示页码
ToolStripButtonbtnNextPage下一页
ToolStripButtonbtnLastPage尾页
ToolStripButtonbtnClose关闭

在这里插入图片描述
一些全局变量

        //打开的PDF文档
        PdfDocument document;
      
        //当前页码
        int curPageNum = 1;
       
        //是否全屏
        bool IsFull = false;
        
        //默认打印机
       string DefaultPrinter = null;

2 打印预览

使用C#自带的接口PrintDialog来实现打印,将PdfiumViewer中的PDF转换成系统的Document 并传递给PrintDialog即可,还可以设置PrintDialog的一些属性,比如开始打印页,总的页数等。

        /// <summary>
        /// 打印预览
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnPrint_Click(object sender, EventArgs e)
        {
            //实例化一个打印预览窗口对象
            using (var form = new PrintDialog())
            using (var doc = document.CreatePrintDocument(PdfPrintMode.CutMargin))
            {//将PdfViwer的PDF的文档 转换为System的document
               
                form.AllowSomePages = true;  //启用"页"
                form.Document = doc;         //设置要显示打印的文档
                form.UseEXDialog = true;
                form.Document.PrinterSettings.FromPage = 1;  //设置起始打印的页码
                form.Document.PrinterSettings.ToPage = document.PageCount;  //总的页码
                if (DefaultPrinter != null)
                    form.Document.PrinterSettings.PrinterName = DefaultPrinter;

                if (form.ShowDialog(FindForm()) == DialogResult.OK)
                {//弹出打印预览的窗口
                    try
                    {
                        if (form.Document.PrinterSettings.FromPage <= document.PageCount)
                            form.Document.Print();
                    }
                    catch
                    {
                        // Ignore exceptions; the printer dialog should take care of this.
                    }
                }
            }
        }

3 放大功能

使用PdfiumViewer的Renderer进行渲染放大页面。

        /// <summary>
        /// 放大
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnZomIn_Click(object sender, EventArgs e)
        {
            pdfViewer1.Renderer.ZoomIn();

        }

4 缩小功能

使用PdfiumViewer的Renderer进行渲染缩小页面。

        /// <summary>
        /// 缩小
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnZomOut_Click(object sender, EventArgs e)
        {
            pdfViewer1.Renderer.ZoomOut();
        }

5 按比例缩放

设置PdfiumViewer的RendererZoom 的属性(缩放比例因子)。

         /// <summary>
        /// 比例缩放
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CbZoomRate_SelectedIndexChanged(object sender, EventArgs e)
        {// 0:25% 1:50%  2:75%  3:100%  4:150%  5:200%  6:Page Width 7:Whole page
           if(cbZoomRate.SelectedIndex ==0 )
            {
                pdfViewer1.Renderer.Zoom = 0.25;
            }
            else if (cbZoomRate.SelectedIndex == 1)
            {
                pdfViewer1.Renderer.Zoom = 0.50;
            }
            else if (cbZoomRate.SelectedIndex == 2)
            {
                pdfViewer1.Renderer.Zoom = 0.75;
            }
            else if (cbZoomRate.SelectedIndex == 3)
            {
                pdfViewer1.Renderer.Zoom = 1.00;
            }
            else if (cbZoomRate.SelectedIndex == 4)
            {
                pdfViewer1.Renderer.Zoom = 1.50;
            }
            else if (cbZoomRate.SelectedIndex == 5)
            {
                pdfViewer1.Renderer.Zoom = 2.00;
            }
            else if(cbZoomRate.SelectedIndex == 6)
            {//page width

                int page = pdfViewer1.Renderer.Page;
                pdfViewer1.ZoomMode = PdfViewerZoomMode.FitWidth;
                pdfViewer1.Renderer.Zoom = 1;
                pdfViewer1.Renderer.Page = page;
            }
            else if (cbZoomRate.SelectedIndex == 7)
            {//Whole page 
                int page = pdfViewer1.Renderer.Page;
                pdfViewer1.ZoomMode = PdfViewerZoomMode.FitHeight;
                pdfViewer1.Renderer.Zoom = 1;
                pdfViewer1.Renderer.Page = page;
            }
        }

订阅了缩放更改事件 pdfViewer1.Renderer.ZoomChanged += Renderer_ZoomChanged; 当使用放大或缩小功能时,更新缩放比例的文本显示。

        /// <summary>
        /// 缩放改变时,显示此时的缩放比例
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Renderer_ZoomChanged(object sender, EventArgs e)
        {
            cbZoomRate.Text = (pdfViewer1.Renderer.Zoom * 100).ToString("f0") + "%";
        }

6 全屏

工具栏有全屏按钮,顺便可以加个鼠标右键菜单可以退出全屏的功能。

        /// <summary>
        /// 窗体最大化显示
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnFullScreen_Click(object sender, EventArgs e)
        {
            IsFull = !IsFull;
                      
            if(IsFull)
            {//全屏

                //隐藏工具栏和状态栏
                this.toolStrip1.Visible = false;
                this.statusStrip1.Visible = false;
                //最大化窗体
                this.FormBorderStyle = FormBorderStyle.None;
                this.WindowState = FormWindowState.Maximized;
            }
            else
            {
                this.toolStrip1.Visible = true;
                this.statusStrip1.Visible = true;

                this.WindowState = FormWindowState.Normal;
                this.FormBorderStyle = FormBorderStyle.FixedDialog;
            }
        }

7 首页和尾页

更改Renderer渲染Page的索引为0,即是首页了。
首页

        /// <summary>
        /// 首页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnFirstPage_Click(object sender, EventArgs e)
        {
             //设置当前页码为1
            curPageNum = 1;
            //渲染页是0 下标从0开始
            pdfViewer1.Renderer.Page = curPageNum - 1;
        }

尾页

       /// <summary>
        /// 尾页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnLastPage_Click(object sender, EventArgs e)
        {
            curPageNum = document.PageCount;

            pdfViewer1.Renderer.Page = curPageNum - 1;

        }

8 上一页和下一页

更改Renderer渲染Page的索引
上一页

        /// <summary>
        /// 上一页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnPreviePage_Click(object sender, EventArgs e)
        {
            //curPageNum 是从1开始计数的,因为工具栏还有一个Label显示当前页的页码
            // 获取当前页页码
            curPageNum = pdfViewer1.Renderer.Page + 1;
            if (curPageNum -1 < 0 )
            {//已经是首页(第1页)了,则返回
                return;
            }
            //当前页减1
            curPageNum--;
            //渲染上一页
            pdfViewer1.Renderer.Page = curPageNum - 1;

        }

下一页

        /// <summary>
        /// 下一页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnNextPage_Click(object sender, EventArgs e)
        {
            //计算当前页
            curPageNum = pdfViewer1.Renderer.Page + 1;
            if (curPageNum    > document.PageCount)
            {//当前页已经是最后一页,则返回
                return;
            }
            //当前页+1,就是下一页
            curPageNum++;
            //因为curPageNum是从1开始计数,而Page下标是从0开始,所以还要减1
            pdfViewer1.Renderer.Page = curPageNum - 1;
        }

9 页码输入框

根据输入的页码,跳转显示PDF文档的页。

        /// <summary>
        /// 设置页码
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TbSetPage_KeyPress(object sender, KeyPressEventArgs e)
        {
            
            string text = tbSetPage.Text.Trim();
            int page = -1;
            //将文本强转为数值
           int.TryParse(text, out page);

            if(page < 0 || page > document.PageCount)
            {//数值超限
                return;
            }
            curPageNum = page;
            //设定跳转的页
            pdfViewer1.Renderer.Page = curPageNum - 1;
        }

10 显示当前预览的页码

订阅 pdfViewer1.Renderer.DisplayRectangleChanged += Renderer_DisplayRectangleChanged; 当显示预览的矩形框变化时,那么预览的页码也可能随之更改。上下翻页,还有设定页,也会触发该事件。

        /// <summary>
        /// 翻页矩形框变化时,更新当前页码
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Renderer_DisplayRectangleChanged(object sender, EventArgs e)
        {
            tbSetPage.Text = (pdfViewer1.Renderer.Page + 1).ToString();
            lbCurrentPage.Text = (pdfViewer1.Renderer.Page + 1).ToString();
        }

小结

1 打印功能:使用自带的PrintDialog 对象(dlg),并将PdfiumViewer中的PdfDocument文档赋值给dlg就可以了。

2 缩放功能:主要是对PdfiumViewer中的组成之一的Renderer的Zoom属性进行设置。

3 换页功能:主要是对PdfiumViewer中的组成之一的Renderer的Page属性进行设置。

4 注意:开源的PdfiumViewer需要与pdfium.dll一起配合使用,放在软件同一目录下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/19400.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

路径规划算法:基于麻雀优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于麻雀优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于麻雀优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化算法麻雀…

Qt使用星空图作为窗口背景,点击键盘的WASD控制小飞机在上面移动。

事件函数的使用依托于Qt的事件机制&#xff0c;一个来自于外部事件的传递机制模型如下所示 信号槽虽然好用&#xff0c;但是无法包含所有的情况&#xff0c;事件函数可以起到对信号槽无法覆盖的一些时机进行补充&#xff0c;事件函数的使用无需连接。 常用的事件函数如下所示。…

【Mysql实战】使用存储过程和计算同比环比

背景 同环比&#xff0c;是基本的数据分析方法。在各类调研表中屡见不鲜&#xff0c;如果人工向前追溯统计数据&#xff0c;可想而知工作量是非常大的。 标题复制10行&#xff0c;并且每行大于10个字符【源码解析】SpringBoot接口参数【Mysql实战】使用存储过程和计算同比环比…

vite跨域问题,你可能需要看这篇文章

最近在学习项目的时候&#xff0c;使用了vite工具进行构建&#xff0c;然后出现了跨域的问题&#xff0c;中间的曲折不过多叙述&#xff0c;直接进入正题。 前端成功启动后的界面&#xff1a; 然后在后端进行的Controller上使用了如下的配置 然后浏览器就会出现跨域的问题 为什…

【论文复现】基于区块链的分布式光伏就地消纳交易模式研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

UE4及Airsim安装时遇到的问题及解决办法

UE4及Airsim安装时遇到的问题及解决办法 目录 UE4及Airsim安装时遇到的问题及解决办法前言UE4下载慢解决方法 Airsim编译过程中提示&#xff1a;无法打开包括文件: “Eigen/Dense”: No such file or directory [D:\software\Visual_studio2022\2022Community\AirSim\Air解决办…

别不信:这些细节关乎你的物联网设备的命运!

《高并发系统实战派》-- 值得拥有 一、设备接入层网络协议的意义 随着物联网的发展&#xff0c;越来越多的设备需要接入云平台进行远程监控和管理。设备接入层网络协议起到了承担设备接入网络的功能&#xff0c;为物联网平台提供了数据交互的基础。设备接入层网络协议对于物联…

【云原生概念和技术】1.2 云原生技术概括(上)

如果想了解或者学习云原生的友友们&#xff0c;欢迎订阅哦&#xff5e;&#x1f917;&#xff0c;目前一周三更&#xff0c;努力码字中&#x1f9d1;‍&#x1f4bb;…目前第一章是一些介绍和概念性的知识&#xff0c;可以先在脑海里有一个知识的轮廓&#xff0c;从第二章开始就…

AUTOSAR入门

简介 AUTOSAR&#xff08;AUTomotive Open System ARchitecture&#xff09;是一种汽车软件架构标准&#xff0c;由德国大陆、博世、宝马等汽车及零部件制造商共同发起&#xff0c;拥有广泛的行业参与。其目标是为了解决汽车电子和软件系统日益复杂的问题&#xff0c;提高可重…

打工人使用ChatGPT的一天!

众所周知&#xff0c;ChatGPT 自去年OpenAI 推出以来&#xff0c;这款 AI 聊天机器人可以说迅速成为了 AI 界的「当红炸子鸡」 作为一名资深的打工人&#x1f477;&#x1f3fb;‍♂️&#xff0c;我们应该怎样利用ChatGPT提高工作效率呢&#xff1f;今天给大家介绍下打工人使…

关于Kerberos认证的一些攻击手法学习总结

Kerberos认证流程 前言 本文主要分享最近学习的关于域内Kerberos认证的一些攻击手法&#xff0c;以自我的理解为主&#xff0c;从原理理解切入到基本工具利用来阐述&#xff0c;个人的理解分析较为啰嗦&#xff0c;嫌太兀长的可以跳着看就好&#xff0c;还请各位谅解。如有错误…

第三十二章 React路由组件的简单使用

1、NavLink的使用 一个特殊版本的 Link&#xff0c;当它与当前 URL 匹配时&#xff0c;为其渲染元素添加样式属性 <NavLink className"list-group-item" to"/home">Home</NavLink> <NavLink className"list-group-item" to&quo…

JVM运行时数据区

Java和C的区别&#xff0c;体现在自动内存分配和垃圾收集技术。 JVM在执行Java程序时&#xff0c;会将它管理的内存分为若干个不同的数据区域。 这些区域有各自的作用范围以及生命周期&#xff1a; 线程私有的区域&#xff0c;随着用户线程的启动和结束而建立和销毁。线程共…

2023网络安全十大顶级工具

从事网络安全工作&#xff0c;手上自然离不开一些重要的网络安全工具。今天&#xff0c;分享10大网络安全工具。 一、Kali Linux Kali 是一个基于 Debian 的 Linux 发行版。它的目标就是为了简单&#xff1a;在一个实用的工具包里尽可能多的包含渗透和审计工具。Kali 实现了这…

MySQL基础(二十二)逻辑架构

1.逻辑架构剖析 1.1 第1层&#xff1a;连接层 系统&#xff08;客户端&#xff09;访问MySQL服务器前&#xff0c;做的第一件事就是建立TCP连接。 经过三次握手建立连接成功后&#xff0c;MySQL服务器对TCP传输过来的账号密码做身份认证、权限获取。 用户名或密码不对&#…

Redis 五大基本数据类型常见命令

一、redis中的常见数据结构 Redis共有5种常见数据结构&#xff0c;分别字符串&#xff08;STRING)、列表&#xff08;LIST&#xff09;、集合&#xff08;SET)、散列&#xff08;HASH&#xff09;、有序集合&#xff08;ZSET)。 二、redis中五大基本数据类型介绍 字符串(Str…

尚硅谷JUC

文章目录 1. 什么是JUC1.1 JUC简介1.2 进程和线程基本概念2.1 Synchronized2.1.1 Synchronized关键字2.1.2 synchronized实现三个线程卖30张票 2.2 Lock2.2.1 什么是Lock2.2.2 使用Lock实现买票功能2.2.3 两者的区别 3. 线程间通信及定制化通信3.1 使用synchronized实现线程之间…

Hive语言

一、Hive的DDL语言&#xff08;数据库、数据表的增删改查操作) 二、Hive的DQL语言&#xff08;数据库查询语言&#xff09; 2.1Hive七子句 聚合函数&#xff1a;count()、sum()、max()、min()、avg()可以单独使用。(缩写&#xff1a;cs mm a) 2.1.1 分区查询与分区裁剪 SELEC…

女生学习软件测试怎么样?

在IT技术行业&#xff0c;女生学习还是有很大优势的。女生相较于男生更有耐心&#xff0c;包容性强&#xff0c;心思细腻&#xff0c;对细节把控更好&#xff0c;同时还能帮助团队男女平衡&#xff0c;活跃气氛。 编程是一个只要你肯学习就会有回报的行业&#xff0c;不论男生…

ResourceManager HA 原理

简介 为了解决 Yarn 中 ResourceManager 的单点故障问题&#xff0c;在 Hadoop 2.4 中新增了 ResourceManager HA 的能力&#xff0c; 该文章基于 Hadoop 3.1.1 进行讲解。 1.1. 名词定义 全称简称备注ResourceManagerRmZookeeperZK ResourceManager Ha 架构 ResourceMana…