【问题标题】:Catch copy/paste of empty text on Windows from AutoHotKey script从 AutoHotKey 脚本捕获 Windows 上空文本的复制/粘贴
【发布时间】:2019-04-22 15:25:50
【问题描述】:

默认情况下,在 Windows 上,复制文本时,它会被放入剪贴板。但是当试图复制 empty 文本时,剪贴板不会被触及。例如,在编辑器中不选择任何文本,然后点击ctrl+c,剪贴板将不会发生任何变化。

问题是,我需要用 AutoHotKey 捕捉这个事件。由于剪贴板没有改变,我不知道如何干净地做到这一点(即没有超时)。

有人知道怎么做吗?

编辑:为了澄清,我从 AutoHotKey 中发送 ctrl+c。我这样做是为了判断是否选择了任何文本,即我正在发送 ctrl+c,然后检查是否有任何文本被复制到剪贴板。问题是,如果没有选择文本,则 AutoHotKey 的剪贴板处理程序永远不会被调用,迫使我使用超时,这不是一个好习惯。

【问题讨论】:

    标签: windows copy-paste autohotkey


    【解决方案1】:

    这就是我所做的。由于剪贴板是 AutoHotkey 中的一个变量,您可以检查它是否为空。我先清了剪贴板,发送control+c,然后看看剪贴板是否还是空的。如果需要,您可以先将当前剪贴板临时移动到一个临时位置。

    ClipSaved := ClipboardAll
    Clipboard =     ; empties the clipboard
    Send ^+{Left}   ;  I just used highlight left to select text, you can replace this with
                 ; whatever your program uses to select an input.
    Send ^c         ; attempt to copy text
    If Clipboard =  ;  checks to see if clipboard is empty
    {
        break  ; Put what you want to do if the clipboard is empty, I used break to stop a loop
    }
    Clipboard := ClipSaved  ; puts the original clipboard contents back
    

    我正在从一个打开的文档中搜索文本,用户可以在其中选择向前或向后的方向。后退时,它会卡在文档开头的循环中。我设置了一个循环限制以防止它成为无限循环,但它仍然浪费时间等待循环完成。如果剪贴板为空,我使用 break 函数结束循环。

    为了在应得的地方给予表扬,我从另一篇文章中获得灵感,该文章有其他提示。它发布了您可以使用此脚本检查空白变量。 http://www.autohotkey.net/~deleyd/xprxmp/autohotkey_expression_examples.htm#J v := ""

    If v =
        MsgBox v = ""
    
    If (v = "")
        MsgBox v = ""
    

    从 AutoHotkey 文档网站我发现了如何临时存储和替换剪贴板内容。 http://www.autohotkey.com/docs/misc/Clipboard.htm

    ClipSaved := ClipboardAll   ; Save the entire clipboard to a variable of your choice.
        ;... here make temporary use of the clipboard, such as for pasting Unicode text via    Transform Unicode ...
    Clipboard := ClipSaved   ; Restore the original clipboard. Note the use of Clipboard    (not ClipboardAll).
    ClipSaved =   ; Free the memory in case the clipboard was very large.
    

    希望这会有所帮助。 塞缪尔

    【讨论】:

    • 问题是 Ctrl+C 需要时间来工作。当您检查剪贴板变量时,完全有可能没有文本出现在剪贴板变量中,但它会在几秒钟后出现。你如何解决这个问题?
    【解决方案2】:

    这是我目前使用的解决方案。基本上,它归结为发送ctrl+c,等待一定的超时时间,然后查看是否实际复制了文本。如果不是,我知道没有选择。

    afaik,没有办法避免等待超时,因为 Windows 需要一定的时间来执行 copy 操作。我将超时设置为 0.15 秒,所以还不错。

    每当我想抓取剪贴板的内容或检查它是否为空时,我都会使用这个函数。我总是先调用这个函数:

    clipped_text :=
    clip_empty := false
    ClipSaved =
    is_clipped := false
    
    clip_speed := 0.15
    
    Clip() {
        global ClipSaved
        global clip_empty
        global clipped_text
        global is_clipped
        global clip_speed
    
        if (!is_clipped) {
            ClipSaved := ClipboardAll   ; Save the entire clipboard to a variable of your choice.
            ; msgbox % ClipSaved
            is_clipped := true
        }
    
        clipboard = ; Empty the clipboard
    
        Send ^{c}
        ClipWait clip_speed
    
        if (ErrorLevel = 1)
        {
            clip_empty := false
        }
        else
        {
            clip_empty := true
            clipped_text := clipboard
        }
    }
    

    我使用这个函数来实际获取剪贴板的内容或检查它是否为空:

    IsTextSelected() {
        global ClipSaved
        global clip_empty
        global clipped_text
    
        if (clip_empty == true) {
            return true
        }
        else {
            return false
        }
    }
    

    要获取剪贴板的内容,我只需查看 clipped_text 变量。

    在执行“Clip()”操作后,我总是调用下面的函数来恢复剪贴板(这个函数被称为once,用于多次调用Clip()):

    UnClip() {
        global ClipSaved
        global clip_empty
        global clipped_text
        global is_clipped
    
        is_clipped := false
        Clipboard := ClipSaved
        ClipSaved =
    }
    

    【讨论】:

      【解决方案3】:

      虽然不是此问题的实际答案,但如果您正在寻找一种在粘贴时捕获文本并在粘贴前对其进行修改的方法,则 Google 搜索可能会将您带到此处。

      这是在 CTRL + V 上从剪贴板粘贴的文本中消除空格的脚本:

      ~^v::
      Trimmed := RegExReplace(Clipboard, "^\s+", "")
      Trimmed := RegExReplace(Trimmed, "\s+$", "")
      Clipboard = %Trimmed%
      SendInput ^v
      return
      

      【讨论】:

        【解决方案4】:

        我想我有一个解决办法。将当前剪贴板放在一边,然后复制。将您复制的内容与空字符串进行比较。如果相等,则复制了某些内容;否则,不会复制任何内容。然后,将剪贴板恢复到您保存的内容。这是一个演示原理的代码示例。

        ^#x::
           ClipSaved := ClipboardAll   ; Save the entire clipboard to a variable of your choice.
           ; ... here make temporary use of the clipboard, such as for pasting Unicode text via Transform Unicode ...
           Clipboard := ; Clear the clipboard
           Send, {CTRLDOWN}c{CTRLUP}
           if (Clipboard = "") {
              Send, you copied nothing
           } else {
              Send, you copied something
           }
           Clipboard := ClipSaved   ; Restore the original clipboard. Note the use of Clipboard (not ClipboardAll).
           ClipSaved =   ; Free the memory in case the clipboard was very large.
        return
        

        实际上,我希望有另一种方法可以简单地测试光标当前是否正在选择任何内容。我在 AutoHotkey 论坛 (http://www.autohotkey.com/forum/posting.php?mode=reply&t=69468) 上问过这个问题,但直到或如果有更好的答案,我将使用上述方法。

        【讨论】:

        • 那行不通。问题是,“ctrl+c”需要时间来工作。在您的代码中,执行“发送,{CTRLDOWN}c{CTRLUP}”后,您将立即检查剪贴板。但整个问题是,在发送“ctrl+c”之后,您应该等待一定的超时时间才能让 Windows 有时间实际执行 ctrl+c 操作。您将遇到选择文本 的极端情况,但您不会识别它。我现在正在用我目前所做的事情添加一个新的答案。
        • “那行不通”。它确实有效。我会记住超时,但过去几天我一直在使用这个,但还没有看到你描述的问题。
        • 这很奇怪。我已经看到问题发生了。例如,我尝试创建一个复制文本的命令,在其周围添加引号,然后将其粘贴回去。 Without a timeout, when a large amount of text is selected, sometimes it will fail to grab the text.这取决于您当前计算机的速度。所以要么你还没有遇到它,要么我有一个错误。
        • 我认为这与电脑的复制速度有关——我只在相对少量的文本上使用了它。我在脚本中使用它来帮助处理 HTML 元素..
        【解决方案5】:

        babylon 脚本(firefox 鼠标中键):

        MButton::
        SetTitleMatchMode, 2
        send {LButton}{LButton}
        Send ^c
        sleep, 100
        send {F10}
        sleep, 100
        SendInput {Raw}%clipboard%
        send {enter}
        Return
        

        【讨论】:

          【解决方案6】:

          我遇到了同样的问题 - 我会发送复制命令,但它不会复制任何内容。我尝试使用计时器无济于事。

          这是我最终做的事情(尝试不同的模式):

          thisclipboard := clipboard . a_now  ;add NOW so that it won't possibly be the same as the contents of the clipboard
              sendplay,^c
              if(clipboard == thisclipboard){
                  sendinput,^c
              }
              if(clipboard == thisclipboard){
                  send,^c
              }
          

          【讨论】:

            【解决方案7】:

            也许您应该改为热键 Ctrl + C,这样每次按下热键时您都会知道。

            您可能希望确保将正常的 Ctrl + C 操作发送到 Windows,以便您可以复制。 考虑这个例子:

            ~^c::
            msgbox, % "Clipboard Changed even if you didnt copy anything"
                    . "(...not really but you tried at least)"
            return
            

            即使您没有将任何内容复制到剪贴板,每次按下 Ctrl + C 时都会触发该消息。同时,您会将 Ctrl + C 的本机功能发送到 Windows,因此如果您复制了某些内容,您的剪贴板将会改变。

            来自帮助文件:

            ~:当热键触发时,其键的本机功能不会被阻止(对系统隐藏)。

            您可能还需要onClipboardChange 来检查剪贴板何时真正更改。

            【讨论】:

            • 问题是,我正在以编程方式发送 ctrl+c,我想查看是否捕获了文本。我正在使用它以编程方式检查是否有选择(即,现在是否选择了文本)。所以这个解决方案对我没有帮助,因为我已经知道 ctrl+c 正在发送,因为我是发送它的人!不过感谢您的创意,我将编辑问题以使其更清晰。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2022-09-23
            • 1970-01-01
            • 2016-07-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-03-05
            相关资源
            最近更新 更多