PDF 输出中的复制到剪贴板功能

PDF 输出中的复制到剪贴板功能

LaTeX 生成的 PDF 文档中是否可以有可点击的“复制到剪贴板”功能?

理想情况下,以宏的形式,还允许在其中嵌入图形元素(例如,制作一个自定义按钮,当单击时,将某些内容复制到剪贴板)。

编辑:仅限 Acrobat 的解决方案也有效。

答案1

我很高兴地报告可能,即使有一些限制:

  • 仅限 Acrobat 的解决方案(但我认为是跨平台的)
  • 您需要信任 PDF(例如“Acrobat Pro DC > 首选项 > 安全(增强) > 添加文件夹路径”),因为它app.execMenuItem("Copy");需要权限。
  • 它并不是那么优雅;它会在一瞬间向你闪现出一个巨大的形状。

话虽如此,这里有一个 MWE:

\documentclass{article}

\usepackage{media9}

\begin{document}

\mediabutton[
    jsaction={
        var fld = this.addField("ToCopy", "text", \thepage-1, this.getPageBox({nPage: \thepage-1})); % Creates field named "ToCopy" of type "text" on the current page of the size of the current page
        fld.value = "never gonna give you up..."; % sets the content of the field
        fld.setFocus(); % selects the content of the field
        app.setTimeOut("app.execMenuItem('Copy');", 1); % copies the selection. 1ms is the lowest pause that worked for me
        app.setTimeOut("this.removeField('ToCopy');", 17); % removes the field. 17ms is the lowest pause that worked for me
    }
]{\fbox{\strut Copy to Clipboard without Alert}}

\mediabutton[
    jsaction={
        var fld = this.addField("ToCopy", "text", \thepage-1, this.getPageBox({nPage: \thepage-1}));
        fld.value = "never gonna let you down...";
        fld.setFocus();
        app.alert("Copied to Clipboard!");
        app.execMenuItem("Copy");
        this.removeField("ToCopy");
    }
]{\fbox{\strut Copy to Clipboard with Alert}}

\end{document}

屏幕录制

  • 为什么表格会占满整个页面?
    • 为了让观众专注于形式,不至于跳来跳去,
    • 确保要复制的文本适合表格(我测试时发现表格太小,内容无法正常显示)。
  • 为什么超时?
    • 没有它,复制命令就不起作用(我最好的猜测是该setFocus命令需要几毫秒才能起作用,并且由于某种原因,该execMenuItem("Copy")命令在前者完成之前执行)。
    • 我不知道为什么复制后需要这么多时间(即删除字段的 17ms(即复制后 16ms)暂停),而使用警报时两个命令之间不需要时间。
  • 难道这不能改进吗?
    • 可能吧,但我找不到使用表单的方法。也许有经验的 Acrobat JavaScript 人士可以提供帮助。

你实际上也可以将它包含在你自己的命令中,例如

\newcommand{\createbutton}[2]{
\mediabutton[
    jsaction={
        var fld = this.addField("ToCopy", "text", \thepage-1, this.getPageBox({nPage: \thepage-1}));
        fld.value = "#2";
        fld.setFocus();
        app.setTimeOut("app.execMenuItem('Copy');", 1);
        app.setTimeOut("this.removeField('ToCopy');", 17);
    }
]{\fbox{\strut #1}}
}

现在,如上所述,在我的计算机上,某些命令之间需要暂停,可以通过setTimeOut(在给定时间过去后执行其参数中的函数)或在其间弹出警报来实现。

我相信我尝试最小化setTimeOut方法中的停顿会对可靠性产生负面影响(例如,我让它在经过一些测试后不删除表格),因此稍微高一点的数字可能更合适(也考虑到不同的机器可能需要更高或更低的停顿)。

但请注意,这次尝试主要是概念验证;我怀疑这在现实世界中是否实用,至少在 PDF 广泛分发的情况下。但我很乐意被证明是错的,尤其是有人改进了这个答案。祝一切顺利!


进一步阅读:

相关内容