如何使用 JavaScript 检测 Ctrl+V、Ctrl+C?

Posted

技术标签:

【中文标题】如何使用 JavaScript 检测 Ctrl+V、Ctrl+C?【英文标题】:How to detect Ctrl+V, Ctrl+C using JavaScript? 【发布时间】:2011-02-23 15:26:02 【问题描述】:

如何使用javascript检测ctrl+vctrl+c

我需要限制在我的 textarea 中粘贴,最终用户不应复制和粘贴内容,用户只能在 textarea 中键入文本。

如何做到这一点?

【问题讨论】:

这样做的目的是什么?我能想到的唯一两个合法场景是密码字段(无论如何您都无法复制)和打字速度测试。我相信您可以检测到可疑的快速输入。 @Paul Butcher, @Propeng:有些场景,你需要这个。非常简单的例子:一个学习外语的网站。如果您手动输入单词而不是使用复制和粘贴,则可以增强学习效果。 另一种合法的情况可能是需要重复输入以检测错误(例如,输入您的电子邮件两次,以便我们知道它没有错字)。尽管如此,这样的用户可能会保留一个随机生成的电子邮件地址列表(例如偷偷摸摸的电子邮件),并且可能希望将其粘贴以确保准确性。 @Paul Butcher - 这根本不是合法的情况,我讨厌这样做的网站,我总是复制/粘贴我的(长) 从一个输入到另一个的电子邮件地址。破坏复制/粘贴是一个主要的可用性问题。它确实让用户感到厌烦,因为它对他们的心智模型如此重要,以至于他们希望它“正常工作”。就好像你试图拉一扇门,它从你身边转开而不是朝你这边转! 每当这样的复制粘贴在页面中是不允许的,我所做的就是将文本粘贴到其他地方(我使用 URL 栏),然后 Ctrl + A(选择刚刚粘贴在url ),在浏览器中拖放禁用粘贴的字段。我想,这在今天是无法预防的。 【参考方案1】:

我只是出于兴趣才这样做。我同意这不是正确的做法,但我认为这应该是操作人员的决定......而且代码可以很容易地扩展以添加功能,而不是把它拿走(比如更高级的剪贴板,或 Ctrl +s 触发服务器端保存)。

$(document).ready(function() 
    var ctrlDown = false,
        ctrlKey = 17,
        cmdKey = 91,
        vKey = 86,
        cKey = 67;

    $(document).keydown(function(e) 
        if (e.keyCode == ctrlKey || e.keyCode == cmdKey) ctrlDown = true;
    ).keyup(function(e) 
        if (e.keyCode == ctrlKey || e.keyCode == cmdKey) ctrlDown = false;
    );

    $(".no-copy-paste").keydown(function(e) 
        if (ctrlDown && (e.keyCode == vKey || e.keyCode == cKey)) return false;
    );
    
    // Document Ctrl + C/V 
    $(document).keydown(function(e) 
        if (ctrlDown && (e.keyCode == cKey)) console.log("Document catch Ctrl+C");
        if (ctrlDown && (e.keyCode == vKey)) console.log("Document catch Ctrl+V");
    );
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h3>Ctrl+c Ctrl+v disabled</h3>
<textarea class="no-copy-paste"></textarea>
<br><br>
<h3>Ctrl+c Ctrl+v allowed</h3>
<textarea></textarea>

另外澄清一下,这个脚本需要 jQuery 库。

Codepen demo

编辑:由于 Tim Down 的建议,删除了 3 条多余的行(涉及 e.which)(参见 cmets)

编辑:添加了对 Mac 的支持(cmd 键而不是 ctrl

【讨论】:

为什么keydownkeyup 处理程序在document 上?您可以在 $(".no-copy-paste").keydown 处理程序中测试 Ctrl 键。此外,不需要e.keyCode || e.which 位:e.keyCode 适用于所有e.which 工作的浏览器,因此永远不会使用e.which。也许您正在考虑如何从keypress 事件中获取字符代码?最后,这对从上下文或编辑菜单中的粘贴没有任何作用,但我想 OP 没有直接询问这个问题。 @Tim:文档上的 Ctrl 键处理程序是通用的 - 因为他们可能不希望 ctrlDown 变量专门链接到无复制粘贴输入。这可能是OTT。感谢 e.which 的提示 - 从那以后我花了半个小时研究 e.keyCode 和 e.which 的不同用例与 keydown() 和 keypress(),真是一团糟(尤其是在 Firefox 中)!跨度> jackocnr:我推荐Jan Wolter的JavaScript密钥处理文章:unixpapa.com/js/key.html我参考了很多次,没有发现错误。 老兄!谢谢!这正是我需要让用户在我正在编写的网络应用程序中选择一个“元素”(日历条目),点击 ctrl + c 来“复制”它,然后 ctrl + v 来“粘贴”它,所有这些都没有实际上与全能的祝福剪贴板进行交互。 ctrl+c 我记得他们点击了什么, ctrl+v 我复制它,每个人都赢了。 我不是专家或任何东西,但我认为最好测试 e.metaKeye.ctrlKeytrue 而不是为键分配数字值并测试它们.【参考方案2】:

使用 jquery,您可以通过绑定函数轻松检测复制、粘贴等:

$("#textA").bind('copy', function() 
    $('span').text('copy behaviour detected!')
); 
$("#textA").bind('paste', function() 
    $('span').text('paste behaviour detected!')
); 
$("#textA").bind('cut', function() 
    $('span').text('cut behaviour detected!')
);

更多信息在这里:http://www.mkyong.com/jquery/how-to-detect-copy-paste-and-cut-behavior-with-jquery/

【讨论】:

不幸的是,如果选择了文本,此方法只会在 Firefox 上触发【参考方案3】:

虽然它在用作反盗版措施时可能很烦人,但我可以看到在某些情况下它可能是合法的,所以:

function disableCopyPaste(elm) 
    // Disable cut/copy/paste key events
    elm.onkeydown = interceptKeys

    // Disable right click events
    elm.oncontextmenu = function() 
        return false
    


function interceptKeys(evt) 
    evt = evt||window.event // IE support
    var c = evt.keyCode
    var ctrlDown = evt.ctrlKey||evt.metaKey // Mac support

    // Check for Alt+Gr (http://en.wikipedia.org/wiki/AltGr_key)
    if (ctrlDown && evt.altKey) return true

    // Check for ctrl+c, v and x
    else if (ctrlDown && c==67) return false // c
    else if (ctrlDown && c==86) return false // v
    else if (ctrlDown && c==88) return false // x

    // Otherwise allow
    return true

我使用了event.ctrlKey,而不是像在 Mac OS X 上的大多数浏览器上那样检查密钥代码 Ctrl/Alt “向下”和“向上”事件永远不会被触发,所以唯一的检测方法是在例如使用event.ctrlKey按住 Ctrl 键后的 c 事件。我还用metaKey 替换了ctrlKey 来代替mac。

此方法的局限性:

Opera 不允许禁用右键单击事件

据我所知,无法阻止浏览器窗口之间的拖放。

edit->copy 菜单项在例如Firefox 仍然可以允许复制/粘贴。

也不能保证对于具有不同键盘布局/语言环境的人来说,复制/粘贴/剪切是相同的键代码(尽管布局通常只遵循与英语相同的标准),但“禁用所有控制键”意味着全选等也将被禁用,所以我认为这是需要做出的妥协。

【讨论】:

【参考方案4】:

还有另一种方法: onpasteoncopyoncut 事件可以在 IE、Firefox、Chrome、Safari 中注册和取消(有一些小问题),唯一不允许取消这些事件的主要浏览器是 Opera。

正如您在我的其他答案中看到的那样,拦截 Ctrl+vCtrl+c 有很多副作用,它仍然不会阻止用户使用 Firefox Edit 菜单等进行粘贴。

function disable_cutcopypaste(e) 
    var fn = function(evt) 
        // IE-specific lines
        evt = evt||window.event
        evt.returnValue = false

        // Other browser support
        if (evt.preventDefault) 
            evt.preventDefault()
        return false
    
    e.onbeforepaste = e.onbeforecopy = e.onbeforecut = fn
    e.onpaste = e.oncopy = e.oncut = fn

Safari 使用此方法仍有一些小问题(当阻止默认设置时,它会清除剪贴板而不是剪切/复制),但该错误似乎已在 Chrome 中得到修复。

另请参阅:http://www.quirksmode.org/dom/events/cutcopypaste.html 和相关的测试页 http://www.quirksmode.org/dom/events/tests/cutcopypaste.html 了解更多信息。

【讨论】:

【参考方案5】:

现场演示: http://jsfiddle.net/abdennour/ba54W/

$(document).ready(function() 

    $("#textA").bind(
        copy : function()
            $('span').text('copy behaviour detected!');
        ,
        paste : function()
            $('span').text('paste behaviour detected!');
        ,
        cut : function()
            $('span').text('cut behaviour detected!');
        
    );

); 

【讨论】:

【参考方案6】:

在jQuery中防止用户使用上下文菜单、复制和剪切的简短解决方案:

jQuery(document).bind("cut copy contextmenu",function(e)
    e.preventDefault();
);

在 CSS 中禁用文本选择也可能会派上用场:

.noselect   
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
     user-select: none;

【讨论】:

【参考方案7】:

如果使用ctrlKey 属性,则不需要维护状态。

   $(document).keydown(function(event) 
      // Ctrl+C or Cmd+C pressed?
      if ((event.ctrlKey || event.metaKey) && event.keyCode == 67) 
         // Do stuff.
      

      // Ctrl+V or Cmd+V pressed?
      if ((event.ctrlKey || event.metaKey) && event.keyCode == 86) 
         // Do stuff.
      

      // Ctrl+X or Cmd+X pressed?
      if ((event.ctrlKey || event.metaKey) && event.keyCode == 88) 
         // Do stuff.
       
    

【讨论】:

这是正确答案!如果按下了某个键,则该事件具有属性 ctrlKey = true。我们不需要任何额外的事件。 这正是我要找的【参考方案8】:

另一种方法(不需要插件)它只使用传入的event object 的ctrlKey 属性。它指示在事件发生时是否按下了 Ctrl,如下所示:

$(document).keypress("c",function(e) 
  if(e.ctrlKey)
    alert("Ctrl+C was pressed!!");
);

另见jquery: keypress, ctrl+c (or some combo like that)。

【讨论】:

【参考方案9】:

我写了一个 jQuery 插件,它可以捕捉击键。它可用于在没有操作系统的情况下启用 html 表单中的多语言脚本输入(字体除外)。大概有300行代码,也许你喜欢看一下:

http://miku.github.com/jquery-retype

一般来说,小心这种改动。我为客户编写了插件,因为没有其他解决方案。

【讨论】:

【参考方案10】:

您可以将此代码用于右键单击、CTRL+CCTRL+V CTRL+X检测并阻止他们的动作

$(document).bind('copy', function(e) 
        alert('Copy is not allowed !!!');
        e.preventDefault();
    ); 
    $(document).bind('paste', function() 
        alert('Paste is not allowed !!!');
        e.preventDefault();
    ); 
    $(document).bind('cut', function() 
        alert('Cut  is not allowed !!!');
        e.preventDefault();
    );
    $(document).bind('contextmenu', function(e) 
        alert('Right Click  is not allowed !!!');
        e.preventDefault();
    );

【讨论】:

【参考方案11】:

使用 onkeydown 代替 onkeypress。

<input type="text" onkeydown="if(event.ctrlKey && event.keyCode==86)return false;" name="txt">

【讨论】:

【参考方案12】:

不要忘记,虽然您可能能够检测并阻止 Ctrl+C/V,但您仍然可以更改某个字段的值。 最好的例子是 Chrome 的 Inspect Element 功能,它允许您更改字段的值属性。

【讨论】:

【参考方案13】:

允许覆盖复制事件的钩子可用于对粘贴事件执行相同操作。输入元素不能显示:无;或可见性:隐藏;很遗憾

export const useOverrideCopy = () => 
  const [copyListenerEl, setCopyListenerEl] = React.useState(
    null as HTMLInputElement | null
  )
  const [, setCopyHandler] = React.useState<(e: ClipboardEvent) => void | null>(
    () => () => 
  )
  // appends a input element to the DOM, that will be focused.
  // when using copy/paste etc, it will target focused elements
  React.useEffect(() => 
    const el = document.createElement("input")  
    // cannot focus a element that is not "visible" aka cannot use display: none or visibility: hidden
    el.style.width = "0"
    el.style.height = "0"
    el.style.opacity = "0"
    el.style.position = "fixed"
    el.style.top = "-20px"
    document.body.appendChild(el)
    setCopyListenerEl(el)
    return () => 
      document.body.removeChild(el)
    
  , [])
  // adds a event listener for copying, and removes the old one 
  const overrideCopy = (newOverrideAction: () => any) => 
    setCopyHandler((prevCopyHandler: (e: ClipboardEvent) => void) => 
      const copyHandler = (e: ClipboardEvent) => 
        e.preventDefault()
        newOverrideAction()
      
      copyListenerEl?.removeEventListener("copy", prevCopyHandler)
      copyListenerEl?.addEventListener("copy", copyHandler)
      copyListenerEl?.focus() // when focused, all copy events will trigger listener above
      return copyHandler
    )
  
  return  overrideCopy 

这样使用:

const customCopyEvent = () => 
    console.log("doing something")
 
const  overrideCopy  = useOverrideCopy()
overrideCopy(customCopyEvent)

每次您调用 overrideCopy 时,它都会重新聚焦并在复制时调用您的自定义事件。

【讨论】:

【参考方案14】:

我已经遇到了你的问题,我通过以下代码解决了它.. 只接受数字

$('#<%= mobileTextBox.ClientID %>').keydown(function(e) 
            ///// e.which Values
            // 8  : BackSpace , 46 : Delete , 37 : Left , 39 : Rigth , 144: Num Lock 
            if (e.which != 8 && e.which != 46 && e.which != 37 && e.which != 39 && e.which != 144
                && (e.which < 96 || e.which > 105 )) 
                return false;
            
        );

你可以检测到 Ctrl id e.which == 17

【讨论】:

【参考方案15】:

重要提示

我使用e.keyCode 有一段时间了,我发现当我按下 ctrl + . 时,此属性返回一个错误的数字,190,而 ascii 码. 是 46!

所以你应该使用 e.key.toUpperCase().charCodeAt(0) 而不是e.keyCode

$(document).keydown(function(event) 
  let keyCode = e.key.toUpperCase().charCodeAt(0);
  
  ...

【讨论】:

那 46 个!不是阶乘。 :)【参考方案16】:

您可以监听 keypress 事件,如果它与特定的键码匹配,则停止默认事件(输入文本)

【讨论】:

【参考方案17】:

有一些方法可以防止它。

但是,用户将始终能够关闭 javascript 或只查看页面的源代码。

一些示例(需要 jQuery)

/**
* Stop every keystroke with ctrl key pressed
*/
$(".textbox").keydown(function()
    if (event.ctrlKey==true) 
        return false;
    
);

/**
* Clear all data of clipboard on focus
*/
$(".textbox").focus(function()
    if ( window.clipboardData ) 
        window.clipboardData.setData('text','');
    
);

/**
* Block the paste event
*/
$(".textbox").bind('paste',function(e)return false;);

编辑:Tim Down 怎么说,这些功能都依赖于浏览器。

【讨论】:

这有很多问题:首先,它在没有paste 事件的浏览器中不起作用,其中包括版本 3 之前的所有版本的 Firefox。其次,@987654323 @ 仅在 IE 中,我相信现在在 IE 中默认禁用。第三,禁用所有按下 Ctrl 键的keydown 事件是多余的:您阻止了有用的键盘快捷键,例如 Ctrl-A(全选)和 Ctrl-Z(撤消)。第四,正如其他人所说,这是一件非常糟糕的事情。 你说得对,并不是在所有浏览器上都可以使用。没有人 ctrl 块确实很烦人。当客户想要阻止“确认电子邮件和密码”字段时,它很方便。

以上是关于如何使用 JavaScript 检测 Ctrl+V、Ctrl+C?的主要内容,如果未能解决你的问题,请参考以下文章

c/c++如何向指定窗口发送ctrl+v然后回车

如何检测 Javascript 中的页面宽度和高度? [复制]

在WPF DataGrid中未检测到CTRL + C.

如何使用 C# 模拟 CTRL+V 击键(粘贴)

在 WPF DataGrid 中未检测到 CTRL + C

javascript检测浏览器的缩放状态实现代码 是指浏览器网页内容的百分比缩放(按Ctrl和+号键或者-号键的缩放)