Code: Select all
#1::
#2::
(new ClipboardHistory).PutHistoryItemIntoClipboard( SubStr(A_ThisHotkey, 2) + 1 )
Send, ^v
Return
class ClipboardHistory
{
; https is.gd /bYyogJ Broken Link for safety ; Clipboard Class (MSDN)
; https is.gd /F2lyI0 Broken Link for safety ; Windows.ApplicationModel.DataTransfer.h (GitHub)
__New() {
static IID_IClipboardStatics2 := "{D2AC1B6A-D29F-554B-B303-F0452345FE02}"
if !(A_OSVersion ~= "^\d") {
MsgBox, This class requires Windows 10 or later!
Return
}
riid := CLSIDFromString(IID_IClipboardStatics2, _)
WinStr := new WindowsString("Windows.ApplicationModel.DataTransfer.Clipboard")
WinStr.CreateInterface(riid, pIClipboardStatics2)
WinStr := ""
this.ClipboardStatics2 := new IClipboardStatics2( pIClipboardStatics2 )
}
__Delete() {
this.ClipboardStatics2 := ""
}
IsHistoryEnabled[] {
get {
Return this.ClipboardStatics2.IsHistoryEnabled
}
}
ClearHistory() {
Return this.ClipboardStatics2.ClearHistory()
}
PutHistoryItemIntoClipboard(index) { ; 1 based
static SetHistoryItemAsContentStatus := ["Success", "AccessDenied", "ItemDeleted"]
if !pIClipboardHistoryItem := this._GetClipboardHistoryItemByIndex(index)
Return
ClipboardHistoryItem := new IClipboardHistoryItem( pIClipboardHistoryItem )
status := this.ClipboardStatics2.SetHistoryItemAsContent( ClipboardHistoryItem.ptr )
Return SetHistoryItemAsContentStatus[ status + 1 ]
}
_GetClipboardHistoryItemByIndex(index) { ; 1 based
static AsyncStatus := ["Started", "Completed", "Canceled", "Error"]
this.ClipboardStatics2.GetHistoryItemsAsync( pIAsyncOperation )
AsyncOperation := new IAsyncOperation( pIAsyncOperation )
AsyncOperation.QueryIAsyncInfo(pIAsyncInfo)
AsyncInfo := new IAsyncInfo( pIAsyncInfo )
Loop {
Sleep, 10
status := AsyncStatus[ AsyncInfo.Status + 1 ]
} until status != "Started" || status = ""
if (status != "Completed") {
MsgBox,, Error, AsyncInfo.Status: "%status%"
Return
}
AsyncOperation.GetResults( pIClipboardHistoryItemsResult )
ClipboardHistoryItemsResult := new IClipboardHistoryItemsResult( pIClipboardHistoryItemsResult )
pIReadOnlyList := ClipboardHistoryItemsResult.Items
ReadOnlyList := new IReadOnlyList( pIReadOnlyList )
if ( ReadOnlyList.Count < index ) {
MsgBox, 48, % " ", Index "%index%" exceeds items count!
Return
}
Return pIClipboardHistoryItem := ReadOnlyList.Item[index - 1]
}
}
class IClipboardStatics2 extends _InterfaceBase
{
GetHistoryItemsAsync(ByRef pIAsyncOperation) {
hr := DllCall(this.VTable(6), "Ptr", this.ptr, "UIntP", pIAsyncOperation)
this.IsError(A_ThisFunc, hr)
}
ClearHistory() {
hr := DllCall(this.VTable(7), "Ptr", this.ptr, "UIntP", res)
this.IsError(A_ThisFunc, hr)
Return res
}
SetHistoryItemAsContent(pIClipboardHistoryItem) {
hr := DllCall(this.VTable(9), "Ptr", this.ptr, "Ptr", pIClipboardHistoryItem, "UIntP", res)
this.IsError(A_ThisFunc, hr)
Return res
}
IsHistoryEnabled[] {
get {
hr := DllCall(this.VTable(10), "Ptr", this.ptr, "UIntP", res)
this.IsError(A_ThisFunc, hr)
Return res
}
}
}
class IClipboardHistoryItemsResult extends _InterfaceBase
{
Items[] {
get {
hr := DllCall(this.VTable(7), "Ptr", this.ptr, "PtrP", pIReadOnlyList)
this.IsError(A_ThisFunc, hr)
Return pIReadOnlyList
}
}
}
class IClipboardHistoryItem extends _InterfaceBase ; <— do not delete!
{
}
class IReadOnlyList extends _InterfaceBase
{
Item[index] {
get {
hr := DllCall(this.VTable(6), "Ptr", this.ptr, "Int", index, "PtrP", pInterface)
this.IsError(A_ThisFunc, hr)
Return pInterface
}
}
Count[] {
get {
hr := DllCall(this.VTable(7), "Ptr", this.ptr, "UIntP", count)
this.IsError(A_ThisFunc, hr)
Return count
}
}
}
class IAsyncOperation extends _InterfaceBase
{
QueryIAsyncInfo(ByRef pIAsyncInfo) {
static IID_IAsyncInfo := "{00000036-0000-0000-C000-000000000046}"
pIAsyncInfo := ComObjQuery(this.ptr, IID_IAsyncInfo)
}
GetResults(ByRef pInterface) {
hr := DllCall(this.VTable(8), "Ptr", this.ptr, "PtrP", pInterface)
this.IsError(A_ThisFunc, hr)
}
}
class IAsyncInfo extends _InterfaceBase
{
Status[] {
get {
hr := DllCall(this.VTable(7), "Ptr", this.ptr, "UIntP", status)
this.IsError(A_ThisFunc, hr)
Return status
}
}
}
class _InterfaceBase {
__New(ptr) {
this.ptr := ptr
}
__Delete() {
ObjRelease(this.ptr)
}
VTable(idx) {
Return NumGet(NumGet(this.ptr + 0) + A_PtrSize*idx)
}
IsError(method, result, exc := true) {
if (result = 0)
Return 0
error := StrReplace(method, ".", "::") . " failed.`nResult: "
. ( result = "" ? "No result" : SysError(Format("{:#x}", result & 0xFFFFFFFF)) )
. "`nErrorLevel: " . ErrorLevel
if !exc
Return error
throw error
}
}
class WindowsString {
__New(string, isHandle := false) {
if isHandle
this.hString := string
else {
DllCall("Combase\WindowsCreateString", "WStr", string, "UInt", StrLen(string), "PtrP", hString)
this.hString := hString
}
}
__Delete() {
DllCall("Combase\WindowsDeleteString", "Ptr", this.hString)
}
Get() {
pBuff := DllCall("Combase\WindowsGetStringRawBuffer", "Ptr", this.hString, "UIntP", len, "Ptr")
Return StrGet(pBuff, len, "UTF-16")
}
CreateInterface(riid, ByRef pInterface) {
hr := DllCall("Combase\RoGetActivationFactory", "Ptr", this.hString, "Ptr", riid, "PtrP", pInterface)
if (hr != 0)
throw SysError(hr)
}
}
CLSIDFromString(IID, ByRef CLSID) {
VarSetCapacity(CLSID, 16, 0)
if hr := DllCall("ole32\CLSIDFromString", "WStr", IID, "Ptr", &CLSID, "UInt")
throw "CLSIDFromString failed. Error: " . Format("{:#x}", hr)
Return &CLSID
}
SysError(ErrorNum = "")
{
static flag := (FORMAT_MESSAGE_ALLOCATE_BUFFER := 0x100) | (FORMAT_MESSAGE_FROM_SYSTEM := 0x1000)
(ErrorNum = "" && ErrorNum := A_LastError)
DllCall("FormatMessage", "UInt", flag, "UInt", 0, "UInt", ErrorNum, "UInt", 0, "PtrP", pBuff, "UInt", 512, "Str", "")
Return (str := StrGet(pBuff)) ? str : ErrorNum
}