excludesHwnds := GetClipboardFormatListenerList() ; 阻止一些剪贴板工具窗口触发

; 当剪贴板数据被请求后显示一个msgbox, 一次性
f1::ClipboardDelayRender(A_Clipboard, () => MsgBox("剪贴板文字已被获取"), excludesHwnds)

; 粘贴后自动还原剪贴板
f2::PasteSend("剪贴板已还原")

PasteSend(str){
  old := A_Clipboard
  ClipboardDelayRender(str, () => A_Clipboard := old, excludesHwnds)
  Send("^v")
}

/*
@param str string 当剪贴板数据被请求时提交至剪贴板的字符串
@param callback func 提交后执行的函数
@param excludes Map 排除的窗口句柄
*/
ClipboardDelayRender(str, callback := unset, excludes := unset) {
  OnMessage(0x0305, WM_RENDERFORMAT, 0) ; 确保回调被更新
  OnMessage(0x0305, WM_RENDERFORMAT)
  DllCall("OpenClipboard", "ptr", A_ScriptHwnd)
  DllCall("EmptyClipboard")
  DllCall("SetClipboardData", "uint", 1, "ptr", 0, "ptr")
  DllCall("CloseClipboard")

  WM_RENDERFORMAT(*) {
    ; 很多剪贴板工具会自动读取剪贴板并触发这段代码, 没有很好的方法精确排除这些窗口
    if IsSet(excludes) && excludes.Has(DllCall("GetOpenClipboardWindow", "ptr"))
      return 0
    hGlobal := DllCall("GlobalAlloc", "uint", 0x0042, "uptr", StrPut(str, "cp0"), "ptr")
    StrPut(str, DllCall("GlobalLock", "ptr", hGlobal, "ptr"), "cp0")
    DllCall("GlobalUnlock", "ptr", hGlobal)
    DllCall("SetClipboardData", "uint", 1, "ptr", hGlobal, "ptr")
    DllCall("ReplyMessage", "ptr", 0)
    IsSet(callback) && callback()
    OnMessage(0x0305, WM_RENDERFORMAT, 0)
    return 0
  }
}

GetClipboardFormatListenerList(){
  tmp := A_Clipboard
  listeners := Map()
  OnMessage(0x0305, WM_RENDERFORMAT)
  DllCall("OpenClipboard", "ptr", A_ScriptHwnd)
  DllCall("EmptyClipboard")
  DllCall("SetClipboardData", "uint", 1, "ptr", 0, "ptr")
  DllCall("CloseClipboard")
  Sleep(250)
  OnMessage(0x0305, WM_RENDERFORMAT, 0)
  A_Clipboard := tmp
  return listeners
  WM_RENDERFORMAT(*) => listeners[DllCall("GetOpenClipboardWindow", "ptr")] := 0
}

 

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。