├── LICENSE.md ├── README.md ├── WinClip.ahk ├── WinClipAPI.ahk └── __Example.ahk /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 TheArkive 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WinClip_ahk2 2 | A direct translation of the old WinClip (from the first reincarnation to v2 - but updated) 3 | 4 | Credits listed [here](https://www.autohotkey.com/boards/viewtopic.php?f=83&t=91054&p=402344#p402344). -------------------------------------------------------------------------------- /WinClip.ahk: -------------------------------------------------------------------------------- 1 | ; AHK v2 2 | 3 | 4 | ; see docs for other examples here: 5 | ; http://www.autohotkey.net/~Deo/index.html 6 | 7 | 8 | 9 | class WinClip extends WinClip_base 10 | { 11 | ClipboardFormats := { CF_BITMAP : 2 ;A handle to a bitmap (HBITMAP). 12 | ,CF_DIB : 8 ;A memory object containing a BITMAPINFO structure followed by the bitmap bits. 13 | ,CF_DIBV5 : 17 ;A memory object containing a BITMAPV5HEADER structure followed by the bitmap color space information and the bitmap bits. 14 | ,CF_DIF : 5 ;Software Arts' Data Interchange Format. 15 | ,CF_DSPBITMAP : 0x0082 ;Bitmap display format associated with a private format. The hMem parameter must be a handle to data that can be displayed in bitmap format in lieu of the privately formatted data. 16 | ,CF_DSPENHMETAFILE : 0x008E ;Enhanced metafile display format associated with a private format. The hMem parameter must be a handle to data that can be displayed in enhanced metafile format in lieu of the privately formatted data. 17 | ,CF_DSPMETAFILEPICT : 0x0083 ;Metafile-picture display format associated with a private format. The hMem parameter must be a handle to data that can be displayed in metafile-picture format in lieu of the privately formatted data. 18 | ,CF_DSPTEXT : 0x0081 ;Text display format associated with a private format. The hMem parameter must be a handle to data that can be displayed in text format in lieu of the privately formatted data. 19 | ,CF_ENHMETAFILE : 14 ;A handle to an enhanced metafile (HENHMETAFILE). 20 | ,CF_GDIOBJFIRST : 0x0300 ;Start of a range of integer values for application-defined GDI object clipboard formats. The end of the range is CF_GDIOBJLAST.Handles associated with clipboard formats in this range are not automatically deleted using the GlobalFree function when the clipboard is emptied. Also, when using values in this range, the hMem parameter is not a handle to a GDI object, but is a handle allocated by the GlobalAlloc function with the GMEM_MOVEABLE flag. 21 | ,CF_GDIOBJLAST : 0x03FF ;See CF_GDIOBJFIRST. 22 | ,CF_HDROP : 15 ;A handle to type HDROP that identifies a list of files. An application can retrieve information about the files by passing the handle to the DragQueryFile function. 23 | ,CF_LOCALE : 16 ;The data is a handle to the locale identifier associated with text in the clipboard. When you close the clipboard, if it contains CF_TEXT data but no CF_LOCALE data, the system automatically sets the CF_LOCALE format to the current input language. You can use the CF_LOCALE format to associate a different locale with the clipboard text. An application that pastes text from the clipboard can retrieve this format to determine which character set was used to generate the text. Note that the clipboard does not support plain text in multiple character sets. To achieve this, use a formatted text data type such as RTF instead. The system uses the code page associated with CF_LOCALE to implicitly convert from CF_TEXT to CF_UNICODETEXT. Therefore, the correct code page table is used for the conversion. 24 | ,CF_METAFILEPICT : 3 ;Handle to a metafile picture format as defined by the METAFILEPICT structure. When passing a CF_METAFILEPICT handle by means of DDE, the application responsible for deleting hMem should also free the metafile referred to by the CF_METAFILEPICT handle. 25 | ,CF_OEMTEXT : 7 ;Text format containing characters in the OEM character set. Each line ends with a carriage return/linefeed (CR-LF) combination. A null character signals the end of the data. 26 | ,CF_OWNERDISPLAY : 0x0080 ;Owner-display format. The clipboard owner must display and update the clipboard viewer window, and receive the WM_ASKCBFORMATNAME, WM_HSCROLLCLIPBOARD, WM_PAINTCLIPBOARD, WM_SIZECLIPBOARD, and WM_VSCROLLCLIPBOARD messages. The hMem parameter must be NULL. 27 | ,CF_PALETTE : 9 ;Handle to a color palette. Whenever an application places data in the clipboard that depends on or assumes a color palette, it should place the palette on the clipboard as well.If the clipboard contains data in the CF_PALETTE (logical color palette) format, the application should use the SelectPalette and RealizePalette functions to realize (compare) any other data in the clipboard against that logical palette.When displaying clipboard data, the clipboard always uses as its current palette any object on the clipboard that is in the CF_PALETTE format. 28 | ,CF_PENDATA : 10 ;Data for the pen extensions to the Microsoft Windows for Pen Computing. 29 | ,CF_PRIVATEFIRST : 0x0200 ;Start of a range of integer values for private clipboard formats. The range ends with CF_PRIVATELAST. Handles associated with private clipboard formats are not freed automatically; the clipboard owner must free such handles, typically in response to the WM_DESTROYCLIPBOARD message. 30 | ,CF_PRIVATELAST : 0x02FF ;See CF_PRIVATEFIRST. 31 | ,CF_RIFF : 11 ;Represents audio data more complex than can be represented in a CF_WAVE standard wave format. 32 | ,CF_SYLK : 4 ;Microsoft Symbolic Link (SYLK) format. 33 | ,CF_TEXT : 1 ;Text format. Each line ends with a carriage return/linefeed (CR-LF) combination. A null character signals the end of the data. Use this format for ANSI text. 34 | ,CF_TIFF : 6 ;Tagged-image file format. 35 | ,CF_UNICODETEXT : 13 ;Unicode text format. Each line ends with a carriage return/linefeed (CR-LF) combination. A null character signals the end of the data. 36 | ,CF_WAVE : 12 } ;Represents audio data in one of the standard wave formats, such as 11 kHz or 22 kHz PCM. 37 | 38 | WM_COPY := 0x301 39 | ,WM_CLEAR := 0x0303 40 | ,WM_CUT := 0x0300 41 | ,WM_PASTE := 0x0302 42 | 43 | skipFormats := { 2 : 0 ;"CF_BITMAP" 44 | ,17 : 0 ;"CF_DIBV5" 45 | ,0x0082 : 0 ;"CF_DSPBITMAP" 46 | ,0x008E : 0 ;"CF_DSPENHMETAFILE" 47 | ,0x0083 : 0 ;"CF_DSPMETAFILEPICT" 48 | ,0x0081 : 0 ;"CF_DSPTEXT" 49 | ,0x0080 : 0 ;"CF_OWNERDISPLAY" 50 | ,3 : 0 ;"CF_METAFILEPICT" 51 | ,7 : 0 ;"CF_OEMTEXT" 52 | ,1 : 0 } ;"CF_TEXT" 53 | 54 | formatByValue := { 2 : "CF_BITMAP" 55 | ,8 : "CF_DIB" 56 | ,17 : "CF_DIBV5" 57 | ,5 : "CF_DIF" 58 | ,0x0082 : "CF_DSPBITMAP" 59 | ,0x008E : "CF_DSPENHMETAFILE" 60 | ,0x0083 : "CF_DSPMETAFILEPICT" 61 | ,0x0081 : "CF_DSPTEXT" 62 | ,14 : "CF_ENHMETAFILE" 63 | ,0x0300 : "CF_GDIOBJFIRST" 64 | ,0x03FF : "CF_GDIOBJLAST" 65 | ,15 : "CF_HDROP" 66 | ,16 : "CF_LOCALE" 67 | ,3 : "CF_METAFILEPICT" 68 | ,7 : "CF_OEMTEXT" 69 | ,0x0080 : "CF_OWNERDISPLAY" 70 | ,9 : "CF_PALETTE" 71 | ,10 : "CF_PENDATA" 72 | ,0x0200 : "CF_PRIVATEFIRST" 73 | ,0x02FF : "CF_PRIVATELAST" 74 | ,11 : "CF_RIFF" 75 | ,4 : "CF_SYLK" 76 | ,1 : "CF_TEXT" 77 | ,6 : "CF_TIFF" 78 | ,13 : "CF_UNICODETEXT" 79 | ,12 : "CF_WAVE" } 80 | 81 | __New() 82 | { 83 | this.isinstance := 1 84 | this.allData := "" 85 | } 86 | 87 | _toclipboard( &data, size ) 88 | { 89 | if !WinClipAPI.OpenClipboard() 90 | return 0 91 | offset := 0 92 | lastPartOffset := 0 93 | WinClipAPI.EmptyClipboard() 94 | while ( offset < size ) 95 | { 96 | if !( fmt := NumGet( data, offset, "UInt" ) ) 97 | break 98 | offset += 4 99 | if !( dataSize := NumGet( data, offset, "UInt" ) ) 100 | break 101 | offset += 4 102 | if ( ( offset + dataSize ) > size ) 103 | break 104 | if !( pData := WinClipAPI.GlobalLock( WinClipAPI.GlobalAlloc( 0x0042, dataSize ) ) ) 105 | { 106 | offset += dataSize 107 | continue 108 | } 109 | WinClipAPI.memcopy( pData, data.ptr + offset, dataSize ) 110 | if ( fmt == this.ClipboardFormats.CF_ENHMETAFILE ) 111 | pClipData := WinClipAPI.SetEnhMetaFileBits( pData, dataSize ) 112 | else 113 | pClipData := pData 114 | if !pClipData 115 | continue 116 | WinClipAPI.SetClipboardData( fmt, pClipData ) 117 | if ( fmt == this.ClipboardFormats.CF_ENHMETAFILE ) 118 | WinClipAPI.DeleteEnhMetaFile( pClipData ) 119 | WinClipAPI.GlobalUnlock( pData ) 120 | offset += dataSize 121 | lastPartOffset := offset 122 | } 123 | WinClipAPI.CloseClipboard() 124 | return lastPartOffset 125 | } 126 | 127 | _fromclipboard( &clipData ) 128 | { 129 | if !WinClipAPI.OpenClipboard() 130 | return 0 131 | nextformat := 0 132 | objFormats := Map() 133 | clipSize := 0 134 | formatsNum := 0 135 | while ( nextformat := WinClipAPI.EnumClipboardFormats( nextformat ) ) 136 | { 137 | if this.skipFormats.HasProp( nextformat ) 138 | continue 139 | if ( dataHandle := WinClipAPI.GetClipboardData( nextformat ) ) 140 | { 141 | pObjPtr := 0, nObjSize := 0 142 | if ( nextformat == this.ClipboardFormats.CF_ENHMETAFILE ) 143 | { 144 | if ( bufSize := WinClipAPI.GetEnhMetaFileBits( dataHandle, &hemfBuf ) ) 145 | pObjPtr := hemfBuf.ptr, nObjSize := bufSize 146 | } 147 | else if ( nSize := WinClipAPI.GlobalSize( WinClipAPI.GlobalLock( dataHandle ) ) ) 148 | pObjPtr := dataHandle, nObjSize := nSize 149 | else 150 | continue 151 | if !( pObjPtr && nObjSize ) 152 | continue 153 | objFormats[ nextformat ] := { handle : pObjPtr, size : nObjSize } 154 | clipSize += nObjSize 155 | formatsNum++ 156 | } 157 | } 158 | structSize := formatsNum*( 4 + 4 ) + clipSize ;allocating 4 bytes for format ID and 4 for data size 159 | if !structSize 160 | { 161 | WinClipAPI.CloseClipboard() 162 | return 0 163 | } 164 | clipData := Buffer( structSize, 0 ) 165 | ; array in form of: 166 | ; format UInt 167 | ; dataSize UInt 168 | ; data Byte[] 169 | offset := 0 170 | for fmt, params in objFormats 171 | { 172 | NumPut( "UInt", fmt, clipData, offset ) 173 | offset += 4 174 | NumPut( "UInt", params.size, clipData, offset ) 175 | offset += 4 176 | WinClipAPI.memcopy( clipData.ptr + offset, params.handle, params.size ) 177 | offset += params.size 178 | WinClipAPI.GlobalUnlock( params.handle ) 179 | } 180 | WinClipAPI.CloseClipboard() 181 | return structSize 182 | } 183 | 184 | _IsInstance( funcName ) 185 | { 186 | if !this.isinstance 187 | { 188 | throw Error( "Error in '" funcName "':`nInstantiate the object first to use this method!", -1 ) 189 | ; return 0 190 | } 191 | return 1 192 | } 193 | 194 | _loadFile( filePath, &Data ) 195 | { 196 | f := FileOpen( filePath, "r","UTF-8" ) 197 | if !IsObject( f ) 198 | return 0 199 | f.Pos := 0 200 | Data := Buffer(f.Length) 201 | dataSize := f.RawRead( Data, f.Length ) 202 | f.close() 203 | return dataSize 204 | } 205 | 206 | _saveFile( filepath, &data, size ) 207 | { 208 | f := FileOpen( filepath, "w","UTF-8" ) 209 | bytes := f.RawWrite( data, size ) 210 | f.close() 211 | return bytes 212 | } 213 | 214 | _setClipData( &data, size ) ; data is Buffer() 215 | { 216 | if !size 217 | return 0 218 | ; if !ObjSetCapacity( this, "allData", size ) 219 | ; return 0 220 | ; if !( pData := ObjGetAddress( this, "allData" ) ) 221 | ; return 0 222 | this.allData := Buffer(size) 223 | WinClipAPI.memcopy( this.allData.ptr, data.ptr, size ) 224 | return size 225 | } 226 | 227 | _getClipData( &data ) 228 | { 229 | ; if !( clipSize := ObjGetCapacity( this, "allData" ) ) 230 | ; return 0 231 | ; if !( pData := ObjGetAddress( this, "allData" ) ) 232 | ; return 0 233 | If (Type(this.allData) != "Buffer") 234 | return 0 235 | data := Buffer( this.allData.size, 0 ) 236 | WinClipAPI.memcopy( data, this.allData.ptr, this.allData.size ) 237 | return this.allData.size 238 | } 239 | 240 | __Delete() 241 | { 242 | ; ObjSetCapacity( this, "allData", 0 ) 243 | this.allData := "" 244 | return 245 | } 246 | 247 | _parseClipboardData( &data, size ) 248 | { 249 | offset := 0 250 | formats := Map() 251 | while ( offset < size ) 252 | { 253 | if !( fmt := NumGet( data, offset, "UInt" ) ) 254 | break 255 | offset += 4 256 | if !( dataSize := NumGet( data, offset, "UInt" ) ) 257 | break 258 | offset += 4 259 | if ( ( offset + dataSize ) > size ) 260 | break 261 | params := { name : this._getFormatName( fmt ), size : dataSize, buffer : Buffer(dataSize) } 262 | ; ObjSetCapacity( params, "buffer", dataSize ) 263 | ; pBuf := ObjGetAddress( params, "buffer" ) 264 | 265 | WinClipAPI.memcopy( params.buffer.ptr, data.ptr + offset, dataSize ) 266 | formats[ fmt ] := params 267 | offset += dataSize 268 | } 269 | return formats 270 | } 271 | 272 | _compileClipData( &out_data, objClip ) 273 | { 274 | if !IsObject( objClip ) 275 | return 0 276 | ;calculating required data size 277 | clipSize := 0 278 | for fmt, params in objClip 279 | clipSize += 8 + params.size 280 | out_data := Buffer( clipSize, 0 ) 281 | offset := 0 282 | for fmt, params in objClip 283 | { 284 | NumPut( "UInt", fmt, out_data, offset ) 285 | offset += 4 286 | NumPut( "UInt", params.size, out_data, offset ) 287 | offset += 4 288 | WinClipAPI.memcopy( out_data.ptr + offset, params.buffer.ptr , params.size ) 289 | offset += params.size 290 | } 291 | return clipSize 292 | } 293 | 294 | GetFormats() 295 | { 296 | if !( clipSize := this._fromclipboard( &clipData ) ) 297 | return 0 298 | return this._parseClipboardData( &clipData, clipSize ) 299 | } 300 | 301 | iGetFormats() 302 | { 303 | this._IsInstance( A_ThisFunc ) 304 | if !( clipSize := this._getClipData( &clipData ) ) 305 | return 0 306 | return this._parseClipboardData( &clipData, clipSize ) 307 | } 308 | 309 | Snap( &data ) 310 | { 311 | return this._fromclipboard( &data ) 312 | } 313 | 314 | iSnap() 315 | { 316 | this._IsInstance( A_ThisFunc ) 317 | if !( dataSize := this._fromclipboard( &clipData ) ) 318 | return 0 319 | return this._setClipData( &clipData, dataSize ) 320 | } 321 | 322 | Restore( &clipData ) 323 | { 324 | clipSize := clipData.size 325 | return this._toclipboard( &clipData, clipSize ) 326 | } 327 | 328 | iRestore() 329 | { 330 | this._IsInstance( A_ThisFunc ) 331 | if !( clipSize := this._getClipData( &clipData ) ) 332 | return 0 333 | return this._toclipboard( &clipData, clipSize ) 334 | } 335 | 336 | Save( filePath ) 337 | { 338 | if !( size := this._fromclipboard( &data ) ) 339 | return 0 340 | return this._saveFile( filePath, &data, size ) 341 | } 342 | 343 | iSave( filePath ) 344 | { 345 | this._IsInstance( A_ThisFunc ) 346 | if !( clipSize := this._getClipData( &clipData ) ) 347 | return 0 348 | return this._saveFile( filePath, &clipData, clipSize ) 349 | } 350 | 351 | Load( filePath ) 352 | { 353 | if !( dataSize := this._loadFile( filePath, &dataBuf ) ) 354 | return 0 355 | return this._toclipboard( &dataBuf, dataSize ) 356 | } 357 | 358 | iLoad( filePath ) 359 | { 360 | this._IsInstance( A_ThisFunc ) 361 | if !( dataSize := this._loadFile( filePath, &dataBuf ) ) 362 | return 0 363 | return this._setClipData( &dataBuf, dataSize ) 364 | } 365 | 366 | Clear() 367 | { 368 | if !WinClipAPI.OpenClipboard() 369 | return 0 370 | WinClipAPI.EmptyClipboard() 371 | WinClipAPI.CloseClipboard() 372 | return 1 373 | } 374 | 375 | iClear() 376 | { 377 | this._IsInstance( A_ThisFunc ) 378 | ; ObjSetCapacity( this, "allData", 0 ) 379 | this.allData := "" 380 | } 381 | 382 | Copy( timeout := 1, method := 1 ) 383 | { 384 | this.Snap( &data ) 385 | this.Clear() ;clearing the clipboard 386 | if( method = 1 ) 387 | SendInput "^{Ins}" 388 | else 389 | SendInput "^{vk43sc02E}" ;ctrl+c 390 | ClipWait timeout, 1 391 | if ( ret := this._isClipEmpty() ) 392 | this.Restore( &data ) 393 | return !ret 394 | } 395 | 396 | iCopy( timeout := 1, method := 1 ) 397 | { 398 | this._IsInstance( A_ThisFunc ) 399 | this.Snap( &data ) 400 | this.Clear() ;clearing the clipboard 401 | if( method = 1 ) 402 | SendInput "^{Ins}" 403 | else 404 | SendInput "^{vk43sc02E}" ;ctrl+c 405 | ClipWait timeout, 1 406 | bytesCopied := 0 407 | if !this._isClipEmpty() 408 | { 409 | this.iClear() ;clearing the variable containing the clipboard data 410 | bytesCopied := this.iSnap() 411 | } 412 | this.Restore( &data ) 413 | return bytesCopied 414 | } 415 | 416 | Paste( plainText := "", method := 1 ) 417 | { 418 | ret := 0 419 | if ( plainText != "" ) 420 | { 421 | this.Snap( &data ) 422 | this.Clear() 423 | ret := this.SetText( plainText ) 424 | } 425 | if( method = 1 ) 426 | SendInput "+{Ins}" 427 | else 428 | SendInput "^{vk56sc02F}" ;ctrl+v 429 | this._waitClipReady( 3000 ) 430 | if ( plainText != "" ) 431 | { 432 | this.Restore( &data ) 433 | } 434 | else 435 | ret := !this._isClipEmpty() 436 | return ret 437 | } 438 | 439 | iPaste( method := 1 ) 440 | { 441 | this._IsInstance( A_ThisFunc ) 442 | this.Snap( &data ) 443 | if !( bytesRestored := this.iRestore() ) 444 | return 0 445 | if( method = 1 ) 446 | SendInput "+{Ins}" 447 | else 448 | SendInput "^{vk56sc02F}" ;ctrl+v 449 | this._waitClipReady( 3000 ) 450 | this.Restore( &data ) 451 | return bytesRestored 452 | } 453 | 454 | IsEmpty() 455 | { 456 | return this._isClipEmpty() 457 | } 458 | 459 | iIsEmpty() 460 | { 461 | return !this.iGetSize() 462 | } 463 | 464 | _isClipEmpty() 465 | { 466 | return !WinClipAPI.CountClipboardFormats() 467 | } 468 | 469 | _waitClipReady( timeout := 10000 ) 470 | { 471 | start_time := A_TickCount 472 | sleep 100 473 | while ( WinClipAPI.GetOpenClipboardWindow() && ( A_TickCount - start_time < timeout ) ) 474 | sleep 100 475 | } 476 | 477 | iSetText( textData ) 478 | { 479 | if ( textData = "" ) 480 | return 0 481 | this._IsInstance( A_ThisFunc ) 482 | clipSize := this._getClipData( &clipData ) 483 | if !( clipSize := this._appendText( &clipData, clipSize, textData, 1 ) ) 484 | return 0 485 | return this._setClipData( &clipData, clipSize ) 486 | } 487 | 488 | SetText( textData ) 489 | { 490 | if ( textData = "" ) 491 | return 0 492 | clipSize := this._fromclipboard( &clipData ) 493 | if !( clipSize := this._appendText( &clipData, clipSize, textData, 1 ) ) 494 | return 0 495 | return this._toclipboard( &clipData, clipSize ) 496 | } 497 | 498 | GetRTF() 499 | { 500 | if !( clipSize := this._fromclipboard( &clipData ) ) 501 | return "" 502 | if !( out_size := this._getFormatData( &out_data, &clipData, clipSize, "Rich Text Format" ) ) 503 | return "" 504 | return strget( &out_data, out_size, "UTF-8" ) 505 | } 506 | 507 | iGetRTF() 508 | { 509 | this._IsInstance( A_ThisFunc ) 510 | if !( clipSize := this._getClipData( &clipData ) ) 511 | return "" 512 | if !( out_size := this._getFormatData( &out_data, &clipData, clipSize, "Rich Text Format" ) ) 513 | return "" 514 | return strget( &out_data, out_size, "UTF-8" ) 515 | } 516 | 517 | SetRTF( textData ) 518 | { 519 | if ( textData = "" ) 520 | return 0 521 | clipSize := this._fromclipboard( &clipData ) 522 | if !( clipSize := this._setRTF( &clipData, clipSize, textData ) ) 523 | return 0 524 | return this._toclipboard( clipData, clipSize ) 525 | } 526 | 527 | iSetRTF( textData ) 528 | { 529 | if ( textData = "" ) 530 | return 0 531 | this._IsInstance( A_ThisFunc ) 532 | clipSize := this._getClipData( &clipData ) 533 | if !( clipSize := this._setRTF( &clipData, clipSize, textData ) ) 534 | return 0 535 | return this._setClipData( &clipData, clipSize ) 536 | } 537 | 538 | _setRTF( &clipData, clipSize, textData ) 539 | { 540 | objFormats := this._parseClipboardData( &clipData, clipSize ) 541 | uFmt := WinClipAPI.RegisterClipboardFormat( "Rich Text Format" ) 542 | objFormats[ uFmt ] := {} 543 | sLen := StrLen( textData ) 544 | objFormats[ uFmt ].buffer := Buffer( sLen ) 545 | StrPut( textData, objFormats[ uFmt ].buffer.ptr, sLen, "UTF-8" ) 546 | objFormats[ uFmt ].size := sLen 547 | return this._compileClipData( &clipData, objFormats ) 548 | } 549 | 550 | iAppendText( textData ) 551 | { 552 | if ( textData = "" ) 553 | return 0 554 | this._IsInstance( A_ThisFunc ) 555 | clipSize := this._getClipData( &clipData ) 556 | if !( clipSize := this._appendText( &clipData, clipSize, textData ) ) 557 | return 0 558 | return this._setClipData( &clipData, clipSize ) 559 | } 560 | 561 | AppendText( textData ) 562 | { 563 | if ( textData = "" ) 564 | return 0 565 | clipSize := this._fromclipboard( &clipData ) 566 | if !( clipSize := this._appendText( &clipData, clipSize, textData ) ) 567 | return 0 568 | return this._toclipboard( &clipData, clipSize ) 569 | } 570 | 571 | SetHTML( html, source := "" ) 572 | { 573 | if ( html = "" ) 574 | return 0 575 | clipSize := this._fromclipboard( &clipData ) 576 | if !( clipSize := this._setHTML( &clipData, clipSize, html, source ) ) 577 | return 0 578 | return this._toclipboard( &clipData, clipSize ) 579 | } 580 | 581 | iSetHTML( html, source := "" ) 582 | { 583 | if ( html = "" ) 584 | return 0 585 | this._IsInstance( A_ThisFunc ) 586 | clipSize := this._getClipData( &clipData ) 587 | if !( clipSize := this._setHTML( &clipData, clipSize, html, source ) ) 588 | return 0 589 | return this._setClipData( &clipData, clipSize ) 590 | } 591 | 592 | _calcHTMLLen( num ) 593 | { 594 | while ( StrLen( num ) < 10 ) 595 | num := "0" . num 596 | return num 597 | } 598 | 599 | _setHTML( &clipData, clipSize, htmlData, source ) 600 | { 601 | objFormats := this._parseClipboardData( &clipData, clipSize ) 602 | uFmt := WinClipAPI.RegisterClipboardFormat( "HTML Format" ) 603 | objFormats[ uFmt ] := {} 604 | encoding := "UTF-8" 605 | htmlLen := StrPut( htmlData, encoding ) - 1 ;substract null 606 | srcLen := 2 + 10 + StrPut( source, encoding ) - 1 ;substract null 607 | StartHTML := this._calcHTMLLen( 105 + srcLen ) 608 | EndHTML := this._calcHTMLLen( StartHTML + htmlLen + 76 ) 609 | StartFragment := this._calcHTMLLen( StartHTML + 38 ) 610 | EndFragment := this._calcHTMLLen( StartFragment + htmlLen ) 611 | 612 | ;replace literal continuation section to make cross-compatible with v1 and v2 613 | html := "Version:0.9`r`n" 614 | html .= "StartHTML:" . StartHTML . "`r`n" 615 | html .= "EndHTML:" . EndHTML . "`r`n" 616 | html .= "StartFragment:" . StartFragment . "`r`n" 617 | html .= "EndFragment:" . EndFragment . "`r`n" 618 | html .= "SourceURL:" . source . "`r`n" 619 | html .= "`r`n" 620 | html .= "`r`n" 621 | html .= "`r`n" 622 | html .= htmlData . "`r`n" 623 | html .= "`r`n" 624 | html .= "`r`n" 625 | html .= "`r`n" 626 | 627 | sLen := StrPut( html, encoding ) 628 | objFormats[ uFmt ].buffer := Buffer( sLen ) 629 | StrPut( html, objFormats[ uFmt ].buffer.ptr, sLen, encoding ) 630 | objFormats[ uFmt ].size := sLen 631 | return this._compileClipData( &clipData, objFormats ) 632 | } 633 | 634 | _appendText( &clipData, clipSize, textData, _IsSet := 0 ) 635 | { 636 | objFormats := this._parseClipboardData( &clipData, clipSize ) 637 | uFmt := this.ClipboardFormats.CF_UNICODETEXT 638 | str := "" 639 | if ( objFormats.has( uFmt ) && !_IsSet ) 640 | str := strget( objFormats[ uFmt ].buffer, "UTF-16" ) 641 | else 642 | objFormats[ uFmt ] := {} 643 | str .= textData 644 | sz := ( (sLen := StrLen( str )) + 1 ) * 2 645 | objFormats[ uFmt ].buffer := Buffer( sz, 0 ) 646 | StrPut( str, objFormats[ uFmt ].buffer, sLen, "UTF-16" ) 647 | objFormats[ uFmt ].size := sz 648 | return this._compileClipData( &clipData, objFormats ) 649 | } 650 | 651 | _getFiles( pDROPFILES ) 652 | { 653 | fWide := numget( pDROPFILES, 16, "uchar" ) ;getting fWide value from DROPFILES struct 654 | pFiles := numget( pDROPFILES, 0, "UInt" ) + pDROPFILES.ptr ;getting address of files list 655 | list := "" 656 | while numget( pFiles + 0, 0, fWide ? "UShort" : "UChar" ) 657 | { 658 | lastPath := strget( pFiles+0, fWide ? "UTF-16" : "UTF-8" ) 659 | list .= ( list ? "`n" : "" ) lastPath 660 | pFiles += ( StrLen( lastPath ) + 1 ) * ( fWide ? 2 : 1 ) 661 | } 662 | return list 663 | } 664 | 665 | _setFiles( &clipData, clipSize, files, append := 0, isCut := 0 ) 666 | { 667 | objFormats := this._parseClipboardData( &clipData, clipSize ) 668 | uFmt := this.ClipboardFormats.CF_HDROP 669 | prevList := '' 670 | if ( append && objFormats.has( uFmt ) ) 671 | prevList := this._getFiles( objFormats[ uFmt ].buffer.ptr ) "`n" 672 | objFiles := WinClipAPI.StrSplit( prevList . files, "`n", A_Space A_Tab ) 673 | objFiles := WinClipAPI.RemoveDubls( objFiles ) 674 | if !objFiles.Length 675 | return 0 676 | objFormats[ uFmt ] := {} 677 | DROP_size := 20 + 2 678 | for i,str in objFiles 679 | DROP_size += ( StrLen( str ) + 1 ) * 2 680 | DROPFILES := Buffer( DROP_size, 0 ) 681 | NumPut( "UInt", 20, DROPFILES, 0 ) ;offset 682 | NumPut( "uchar", 1, DROPFILES, 16 ) ;NumPut( 20, DROPFILES, 0, "UInt" ) 683 | offset := DROPFILES.ptr + 20 684 | for i,str in objFiles 685 | { 686 | StrPut( str, offset, "UTF-16" ) 687 | offset += ( StrLen( str ) + 1 ) * 2 688 | } 689 | objFormats[ uFmt ].buffer := Buffer( DROP_size ) 690 | WinClipAPI.memcopy( objFormats[ uFmt ].buffer.ptr, DROPFILES.ptr, DROP_size ) 691 | objFormats[ uFmt ].size := DROP_size 692 | prefFmt := WinClipAPI.RegisterClipboardFormat( "Preferred DropEffect" ) 693 | objFormats[ prefFmt ] := { size : 4 } 694 | objFormats[ prefFmt ].buffer := Buffer( 4 ) 695 | NumPut( "UInt", isCut ? 2 : 5, objFormats[ prefFmt ].buffer.ptr, 0 ) 696 | return this._compileClipData( &clipData, objFormats ) 697 | } 698 | 699 | SetFiles( files, isCut := 0 ) 700 | { 701 | if ( files = "" ) 702 | return 0 703 | clipSize := this._fromclipboard( &clipData ) 704 | if !( clipSize := this._setFiles( &clipData, clipSize, files, 0, isCut ) ) 705 | return 0 706 | return this._toclipboard( &clipData, clipSize ) 707 | } 708 | 709 | iSetFiles( files, isCut := 0 ) 710 | { 711 | this._IsInstance( A_ThisFunc ) 712 | if ( files = "" ) 713 | return 0 714 | clipSize := this._getClipData( &clipData ) 715 | if !( clipSize := this._setFiles( &clipData, clipSize, files, 0, isCut ) ) 716 | return 0 717 | return this._setClipData( &clipData, clipSize ) 718 | } 719 | 720 | AppendFiles( files, isCut := 0 ) 721 | { 722 | if ( files = "" ) 723 | return 0 724 | clipSize := this._fromclipboard( &clipData ) 725 | if !( clipSize := this._setFiles( &clipData, clipSize, files, 1, isCut ) ) 726 | return 0 727 | return this._toclipboard( clipData, clipSize ) 728 | } 729 | 730 | iAppendFiles( files, isCut := 0 ) 731 | { 732 | this._IsInstance( A_ThisFunc ) 733 | if ( files = "" ) 734 | return 0 735 | clipSize := this._getClipData( &clipData ) 736 | if !( clipSize := this._setFiles( &clipData, clipSize, files, 1, isCut ) ) 737 | return 0 738 | return this._setClipData( &clipData, clipSize ) 739 | } 740 | 741 | GetFiles() 742 | { 743 | if !( clipSize := this._fromclipboard( &clipData ) ) 744 | return "" 745 | if !( out_size := this._getFormatData( &out_data, &clipData, clipSize, this.ClipboardFormats.CF_HDROP ) ) 746 | return "" 747 | return this._getFiles( out_data ) 748 | } 749 | 750 | iGetFiles() 751 | { 752 | this._IsInstance( A_ThisFunc ) 753 | if !( clipSize := this._getClipData( &clipData ) ) 754 | return "" 755 | if !( out_size := this._getFormatData( &out_data, &clipData, clipSize, this.ClipboardFormats.CF_HDROP ) ) 756 | return "" 757 | return this._getFiles( out_data ) 758 | } 759 | 760 | _getFormatData( &out_data, &data, size, needleFormat ) 761 | { 762 | needleFormat := (WinClipAPI.IsInteger( needleFormat ) ? needleFormat : WinClipAPI.RegisterClipboardFormat( needleFormat )) 763 | if !needleFormat 764 | return 0 765 | offset := 0 766 | while ( offset < size ) 767 | { 768 | if !( fmt := NumGet( data, offset, "UInt" ) ) 769 | break 770 | offset += 4 771 | if !( dataSize := NumGet( data, offset, "UInt" ) ) 772 | break 773 | offset += 4 774 | if ( fmt == needleFormat ) 775 | { 776 | out_data := Buffer( dataSize, 0 ) 777 | WinClipAPI.memcopy( out_data.ptr, data.ptr + offset, dataSize ) 778 | return dataSize 779 | } 780 | offset += dataSize 781 | } 782 | return 0 783 | } 784 | 785 | _DIBtoHBITMAP( &dibData ) 786 | { 787 | ;http://ebersys.blogspot.com/2009/06/how-to-convert-dib-to-bitmap.html 788 | pPix := WinClipAPI.GetPixelInfo( &dibData ) ; should be Buffer() ? 789 | gdip_token := WinClipAPI.Gdip_Startup() 790 | DllCall("gdiplus\GdipCreateBitmapFromGdiDib", "Ptr", dibData.ptr, "Ptr", pPix, "Ptr*", &pBitmap:=0 ) 791 | DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "Ptr*", &hBitmap:=0, "int", 0xffffffff ) 792 | DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap) 793 | WinClipAPI.Gdip_Shutdown( gdip_token ) 794 | return hBitmap 795 | } 796 | 797 | GetBitmap() 798 | { 799 | if !( clipSize := this._fromclipboard( &clipData ) ) 800 | return "" 801 | if !( out_size := this._getFormatData( &out_data, &clipData, clipSize, this.ClipboardFormats.CF_DIB ) ) 802 | return "" 803 | return this._DIBtoHBITMAP( &out_data ) 804 | } 805 | 806 | iGetBitmap() 807 | { 808 | this._IsInstance( A_ThisFunc ) 809 | if !( clipSize := this._getClipData( &clipData ) ) 810 | return "" 811 | if !( out_size := this._getFormatData( &out_data, &clipData, clipSize, this.ClipboardFormats.CF_DIB ) ) 812 | return "" 813 | return this._DIBtoHBITMAP( &out_data ) 814 | } 815 | 816 | _BITMAPtoDIB( bitmap, &DIB ) 817 | { 818 | A_ThisLabel := "" 819 | if !bitmap 820 | return 0 821 | if !WinClipAPI.IsInteger( bitmap ) 822 | { 823 | gdip_token := WinClipAPI.Gdip_Startup() 824 | DllCall("gdiplus\GdipCreateBitmapFromFileICM", "wstr", bitmap, "Ptr*", &pBitmap:=0 ) 825 | DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "Ptr*", &hBitmap:=0, "int", 0xffffffff ) 826 | DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap) 827 | WinClipAPI.Gdip_Shutdown( gdip_token ) 828 | bmMade := 1 829 | } 830 | else 831 | hBitmap := bitmap, bmMade := 0 832 | if !hBitmap 833 | return 0 834 | ;http://www.codeguru.com/Cpp/G-M/bitmap/article.php/c1765 835 | if !( hdc := DllCall( "GetDC", "Ptr", 0 ) ) 836 | goto _BITMAPtoDIB_cleanup 837 | hPal := DllCall( "GetStockObject", "UInt", 15 ) ;DEFAULT_PALLETE 838 | hPal := DllCall( "SelectPalette", "ptr", hdc, "ptr", hPal, "Uint", 0 ) 839 | DllCall( "RealizePalette", "ptr", hdc ) 840 | size := DllCall( "GetObject", "Ptr", hBitmap, "Uint", 0, "ptr", 0 ) 841 | bm := Buffer( size, 0 ) 842 | DllCall( "GetObject", "Ptr", hBitmap, "Uint", size, "ptr", bm.ptr ) 843 | biBitCount := NumGet( bm, 16, "UShort" )*NumGet( bm, 18, "UShort" ) 844 | nColors := (1 << biBitCount) 845 | if ( nColors > 256 ) 846 | nColors := 0 847 | bmiLen := 40 + nColors * 4 848 | bmi := Buffer( bmiLen, 0 ) 849 | ;BITMAPINFOHEADER initialization 850 | NumPut( "UInt", 40, bmi, 0 ) 851 | NumPut( "UInt", NumGet( bm, 4, "Uint" ), bmi, 4 ) ;width 852 | NumPut( "UInt", biHeight := NumGet( bm, 8, "Uint" ), bmi, 8 ) ;height 853 | NumPut( "UShort", 1, bmi, 12 ) 854 | NumPut( "UShort", biBitCount, bmi, 14 ) 855 | NumPut( "UInt", 0, bmi, 16 ) ;compression must be BI_RGB 856 | 857 | ; Get BITMAPINFO. 858 | if !DllCall("GetDIBits" 859 | ,"ptr",hdc 860 | ,"ptr",hBitmap 861 | ,"uint",0 862 | ,"uint",biHeight 863 | ,"ptr",0 ;lpvBits 864 | ,"uptr",bmi.ptr ;lpbi 865 | ,"uint",0) ;DIB_RGB_COLORS 866 | goto _BITMAPtoDIB_cleanup 867 | biSizeImage := NumGet( bmi, 20, "UInt" ) 868 | if ( biSizeImage = 0 ) 869 | { 870 | biBitCount := numget( bmi, 14, "UShort" ) 871 | biWidth := numget( bmi, 4, "UInt" ) 872 | biHeight := numget( bmi, 8, "UInt" ) 873 | biSizeImage := (((( biWidth * biBitCount + 31 ) & ~31 ) >> 3 ) * biHeight ) 874 | ;~ dwCompression := numget( bmi, 16, "UInt" ) 875 | ;~ if ( dwCompression != 0 ) ;BI_RGB 876 | ;~ biSizeImage := ( biSizeImage * 3 ) / 2 877 | numput( "UInt", biSizeImage, bmi, 20 ) 878 | } 879 | DIBLen := bmiLen + biSizeImage 880 | DIB := Buffer( DIBLen, 0 ) 881 | WinClipAPI.memcopy( DIB.ptr, bmi.ptr, bmiLen ) 882 | if !DllCall("GetDIBits" 883 | ,"ptr",hdc 884 | ,"ptr",hBitmap 885 | ,"uint",0 886 | ,"uint",biHeight 887 | ,"ptr",DIB.ptr + bmiLen ;lpvBits 888 | ,"ptr",DIB.ptr ;lpbi 889 | ,"uint",0) { ;DIB_RGB_COLORS 890 | A_ThisLabel := "_BITMAPtoDIB_cleanup" 891 | goto _BITMAPtoDIB_cleanup 892 | } 893 | _BITMAPtoDIB_cleanup: 894 | if bmMade 895 | DllCall( "DeleteObject", "ptr", hBitmap ) 896 | DllCall( "SelectPalette", "ptr", hdc, "ptr", hPal, "Uint", 0 ) 897 | DllCall( "RealizePalette", "ptr", hdc ) 898 | DllCall("ReleaseDC","ptr",hdc) 899 | if ( A_ThisLabel = "_BITMAPtoDIB_cleanup" ) 900 | return 0 901 | return DIBLen 902 | } 903 | 904 | _setBitmap( &DIB, DIBSize, &clipData, clipSize ) 905 | { 906 | objFormats := this._parseClipboardData( &clipData, clipSize ) 907 | uFmt := this.ClipboardFormats.CF_DIB 908 | objFormats[ uFmt ] := { size : DIBSize } 909 | objFormats[ uFmt ].buffer := Buffer( DIBSize ) 910 | WinClipAPI.memcopy( objFormats[ uFmt ].buffer.ptr, DIB.ptr, DIBSize ) 911 | return this._compileClipData( &clipData, objFormats ) 912 | } 913 | 914 | SetBitmap( bitmap ) 915 | { 916 | if ( DIBSize := this._BITMAPtoDIB( bitmap, &DIB ) ) 917 | { 918 | clipSize := this._fromclipboard( &clipData ) 919 | if ( clipSize := this._setBitmap( &DIB, DIBSize, &clipData, clipSize ) ) 920 | return this._toclipboard( &clipData, clipSize ) 921 | } 922 | return 0 923 | } 924 | 925 | iSetBitmap( bitmap ) 926 | { 927 | this._IsInstance( A_ThisFunc ) 928 | if ( DIBSize := this._BITMAPtoDIB( bitmap, &DIB ) ) 929 | { 930 | clipSize := this._getClipData( &clipData ) 931 | if ( clipSize := this._setBitmap( &DIB, DIBSize, &clipData, clipSize ) ) 932 | return this._setClipData( &clipData, clipSize ) 933 | } 934 | return 0 935 | } 936 | 937 | GetText() 938 | { 939 | if !( clipSize := this._fromclipboard( &clipData ) ) 940 | return "" 941 | if !( out_size := this._getFormatData( &out_data, &clipData, clipSize, this.ClipboardFormats.CF_UNICODETEXT ) ) 942 | return "" 943 | return strget( out_data, out_size / 2, "UTF-16" ) 944 | } 945 | 946 | iGetText() 947 | { 948 | this._IsInstance( A_ThisFunc ) 949 | if !( clipSize := this._getClipData( &clipData ) ) 950 | return "" 951 | if !( out_size := this._getFormatData( &out_data, &clipData, clipSize, this.ClipboardFormats.CF_UNICODETEXT ) ) 952 | return "" 953 | return strget( out_data, out_size / 2, "UTF-16" ) 954 | } 955 | 956 | GetHtml() 957 | { 958 | if !( clipSize := this._fromclipboard( &clipData ) ) 959 | return "" 960 | if !( out_size := this._getFormatData( &out_data, &clipData, clipSize, "HTML Format" ) ) 961 | return "" 962 | return strget( out_data, out_size, "UTF-8" ) 963 | } 964 | 965 | iGetHtml() 966 | { 967 | this._IsInstance( A_ThisFunc ) 968 | if !( clipSize := this._getClipData( &clipData ) ) 969 | return "" 970 | if !( out_size := this._getFormatData( &out_data, &clipData, clipSize, "HTML Format" ) ) 971 | return "" 972 | return strget( out_data, out_size, "UTF-8" ) 973 | } 974 | 975 | _getFormatName( iformat ) 976 | { 977 | if this.formatByValue.HasProp( iformat ) 978 | return this.formatByValue.%iformat% 979 | else 980 | return WinClipAPI.GetClipboardFormatName( iformat ) 981 | } 982 | 983 | iGetData( &Data ) 984 | { 985 | this._IsInstance( A_ThisFunc ) 986 | return this._getClipData( Data.ptr ) 987 | } 988 | 989 | iSetData( &data ) 990 | { 991 | this._IsInstance( A_ThisFunc ) 992 | return this._setClipData( data.ptr, data.size ) 993 | } 994 | 995 | iGetSize() 996 | { 997 | this._IsInstance( A_ThisFunc ) 998 | return this.alldata.size 999 | } 1000 | 1001 | HasFormat( fmt ) 1002 | { 1003 | if !fmt 1004 | return 0 1005 | return WinClipAPI.IsClipboardFormatAvailable( WinClipAPI.IsInteger( fmt ) ? fmt : WinClipAPI.RegisterClipboardFormat( fmt ) ) 1006 | } 1007 | 1008 | iHasFormat( fmt ) 1009 | { 1010 | this._IsInstance( A_ThisFunc ) 1011 | if !( clipSize := this._getClipData( &clipData ) ) 1012 | return 0 1013 | return this._hasFormat( &clipData, clipSize, fmt ) 1014 | } 1015 | 1016 | _hasFormat( &data, size, needleFormat ) 1017 | { 1018 | needleFormat := WinClipAPI.IsInteger( needleFormat ) ? needleFormat : WinClipAPI.RegisterClipboardFormat( needleFormat ) 1019 | if !needleFormat 1020 | return 0 1021 | offset := 0 1022 | while ( offset < size ) 1023 | { 1024 | if !( fmt := NumGet( data, offset, "UInt" ) ) 1025 | break 1026 | if ( fmt == needleFormat ) 1027 | return 1 1028 | offset += 4 1029 | if !( dataSize := NumGet( data, offset, "UInt" ) ) 1030 | break 1031 | offset += 4 + dataSize 1032 | } 1033 | return 0 1034 | } 1035 | 1036 | iSaveBitmap( filePath, format ) 1037 | { 1038 | this._IsInstance( A_ThisFunc ) 1039 | if ( filePath = "" || format = "" ) 1040 | return 0 1041 | if !( clipSize := this._getClipData( &clipData ) ) 1042 | return 0 1043 | if !( DIBsize := this._getFormatData( &DIB, &clipData, clipSize, this.ClipboardFormats.CF_DIB ) ) 1044 | return 0 1045 | gdip_token := WinClipAPI.Gdip_Startup() 1046 | if !WinClipAPI.GetEncoderClsid( format, &CLSID ) 1047 | return 0 1048 | DllCall("gdiplus\GdipCreateBitmapFromGdiDib", "Ptr", DIB.ptr, "Ptr", WinClipAPI.GetPixelInfo( DIB.ptr ), "Ptr*", &pBitmap:=0 ) 1049 | DllCall("gdiplus\GdipSaveImageToFile", "Ptr", pBitmap, "wstr", filePath, "Ptr", CLSID.ptr, "Ptr", 0 ) 1050 | DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap) 1051 | WinClipAPI.Gdip_Shutdown( gdip_token ) 1052 | return 1 1053 | } 1054 | 1055 | SaveBitmap( filePath, format ) 1056 | { 1057 | if ( filePath = "" || format = "" ) 1058 | return 0 1059 | if !( clipSize := this._fromclipboard( &clipData ) ) 1060 | return 0 1061 | if !( DIBsize := this._getFormatData( &DIB, &clipData, clipSize, this.ClipboardFormats.CF_DIB ) ) 1062 | return 0 1063 | gdip_token := WinClipAPI.Gdip_Startup() 1064 | if !WinClipAPI.GetEncoderClsid( format, &CLSID ) 1065 | return 0 1066 | DllCall("gdiplus\GdipCreateBitmapFromGdiDib", "Ptr", DIB.ptr, "Ptr", WinClipAPI.GetPixelInfo( DIB.ptr ), "Ptr*", &pBitmap:=0 ) 1067 | DllCall("gdiplus\GdipSaveImageToFile", "Ptr", pBitmap, "wstr", filePath, "Ptr", CLSID.ptr, "Ptr", 0 ) 1068 | DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap) 1069 | WinClipAPI.Gdip_Shutdown( gdip_token ) 1070 | return 1 1071 | } 1072 | } 1073 | -------------------------------------------------------------------------------- /WinClipAPI.ahk: -------------------------------------------------------------------------------- 1 | class WinClip_base 2 | { 3 | Static __Call( aTarget, aParams ) { ; 2nd param already is an array, so omit "*" 4 | if ObjHasOwnProp( WinClip_base, aTarget ) 5 | return this.%aTarget%(this, aParams*) ; updated again for AHKv2 6 | ; return WinClip_base[ aTarget ].Call( this, aParams* ) ;updated for AHKv2 compatibility 7 | ;return WinClip_base[ aTarget ].( this, aParams* ) 8 | throw Error( "Unknown function '" aTarget "' requested from object '" this.__Class "'", -1 ) 9 | } 10 | 11 | Static Err( msg ) { 12 | throw Error( this.__Class " : " msg ( (A_LastError != 0) ? "`n" this.ErrorFormat( A_LastError ) : "" ), -2 ) 13 | } 14 | 15 | Static ErrorFormat( error_id ) { 16 | msg := Buffer(1000,0) 17 | if !len := DllCall("FormatMessageW" 18 | ,"UInt",FORMAT_MESSAGE_FROM_SYSTEM := 0x00001000 | FORMAT_MESSAGE_IGNORE_INSERTS := 0x00000200 ;dwflags 19 | ,"Ptr",0 ;lpSource 20 | ,"UInt",error_id ;dwMessageId 21 | ,"UInt",0 ;dwLanguageId 22 | ,"Ptr",msg.ptr ;lpBuffer 23 | ,"UInt",500) ;nSize 24 | return 25 | return strget(msg,len) 26 | } 27 | } 28 | 29 | class WinClipAPI_base extends WinClip_base 30 | { 31 | Static __Get( name, initialized ) { ; ??? initialized seemed like an undefined var, on next line 32 | if !ObjHasOwnProp( this, initialized* ) 33 | this.Init() 34 | else 35 | throw Error( "Unknown field '" name "' requested from object '" this.__Class "'", -1 ) 36 | } 37 | } 38 | 39 | class WinClipAPI extends WinClip_base 40 | { 41 | static u := StrLen(Chr(0xFFFF)) ; IsUnicode 42 | static m := (this.u)?2:1 ; Unicode/Ansi str buffer multiplier 43 | 44 | Static memcopy( dest, src, size ) { 45 | return DllCall( "msvcrt\memcpy", "ptr", dest, "ptr", src, "uint", size ) 46 | } 47 | Static GlobalSize( hObj ) { 48 | return DllCall( "GlobalSize", "Ptr", hObj ) 49 | } 50 | Static GlobalLock( hMem ) { 51 | return DllCall( "GlobalLock", "Ptr", hMem ) 52 | } 53 | Static GlobalUnlock( hMem ) { 54 | return DllCall( "GlobalUnlock", "Ptr", hMem ) 55 | } 56 | Static GlobalAlloc( flags, size ) { 57 | return DllCall( "GlobalAlloc", "Uint", flags, "Uint", size ) 58 | } 59 | Static OpenClipboard() { 60 | return DllCall( "OpenClipboard", "Ptr", 0 ) 61 | } 62 | Static CloseClipboard() { 63 | return DllCall( "CloseClipboard" ) 64 | } 65 | Static SetClipboardData( format, hMem ) { 66 | return DllCall( "SetClipboardData", "Uint", format, "Ptr", hMem ) 67 | } 68 | Static GetClipboardData( format ) { 69 | return DllCall( "GetClipboardData", "Uint", format ) 70 | } 71 | Static EmptyClipboard() { 72 | return DllCall( "EmptyClipboard" ) 73 | } 74 | Static EnumClipboardFormats( format ) { 75 | return DllCall( "EnumClipboardFormats", "UInt", format ) 76 | } 77 | Static CountClipboardFormats() { 78 | return DllCall( "CountClipboardFormats" ) 79 | } 80 | Static GetClipboardFormatName( iFormat ) { 81 | bufName := Buffer( 255*( this.m ), 0 ) 82 | DllCall( "GetClipboardFormatName", "Uint", iFormat, "UPtr", bufName.ptr, "Uint", bufName.size ) 83 | return bufName 84 | } 85 | Static GetEnhMetaFileBits( hemf, &buf ) { 86 | if !( bufSize := DllCall( "GetEnhMetaFileBits", "Ptr", hemf, "Uint", 0, "Ptr", 0 ) ) 87 | return 0 88 | buf := Buffer( bufSize, 0 ) 89 | if !( bytesCopied := DllCall( "GetEnhMetaFileBits", "Ptr", hemf, "Uint", bufSize, "Ptr", buf.ptr ) ) 90 | return 0 91 | return bytesCopied 92 | } 93 | Static SetEnhMetaFileBits( pBuf, bufSize ) { 94 | return DllCall( "SetEnhMetaFileBits", "Uint", bufSize, "Ptr", pBuf ) 95 | } 96 | Static DeleteEnhMetaFile( hemf ) { 97 | return DllCall( "DeleteEnhMetaFile", "Ptr", hemf ) 98 | } 99 | Static ErrorFormat(error_id) { 100 | msg := Buffer(1000,0) 101 | if !len := DllCall("FormatMessageW" 102 | ,"UInt",FORMAT_MESSAGE_FROM_SYSTEM := 0x00001000 | FORMAT_MESSAGE_IGNORE_INSERTS := 0x00000200 ;dwflags 103 | ,"Ptr",0 ;lpSource 104 | ,"UInt",error_id ;dwMessageId 105 | ,"UInt",0 ;dwLanguageId 106 | ,"Ptr",msg.ptr ;lpBuffer 107 | ,"UInt",500) ;nSize 108 | return 109 | return strget(msg,len) 110 | } 111 | Static IsInteger( var ) { 112 | ; if (var+0 == var) && (Floor(var) == var) ;test for integer while remaining v1 and v2 compatible 113 | ; return True 114 | ; else 115 | ; return False 116 | return IsInteger(var) 117 | } 118 | Static LoadDllFunction( file, function ) { 119 | if !hModule := DllCall( "GetModuleHandleW", "Wstr", file, "UPtr" ) 120 | hModule := DllCall( "LoadLibraryW", "Wstr", file, "UPtr" ) 121 | 122 | ret := DllCall("GetProcAddress", "Ptr", hModule, "AStr", function, "UPtr") 123 | return ret 124 | } 125 | Static SendMessage( hWnd, Msg, wParam, lParam ) { 126 | static SendMessageW 127 | 128 | If not SendMessageW 129 | SendMessageW := this.LoadDllFunction( "user32.dll", "SendMessageW" ) 130 | 131 | ret := DllCall( SendMessageW, "UPtr", hWnd, "UInt", Msg, "UPtr", wParam, "UPtr", lParam ) 132 | return ret 133 | } 134 | Static GetWindowThreadProcessId( hwnd ) { 135 | return DllCall( "GetWindowThreadProcessId", "Ptr", hwnd, "Ptr", 0 ) 136 | } 137 | Static WinGetFocus( hwnd ) { 138 | GUITHREADINFO_cbsize := 24 + A_PtrSize*6 139 | GuiThreadInfo := Buffer( GUITHREADINFO_cbsize, 0 ) ;GuiThreadInfoSize = 48 140 | NumPut("UInt", GUITHREADINFO_cbsize, GuiThreadInfo, 0) 141 | threadWnd := this.GetWindowThreadProcessId( hwnd ) 142 | if not DllCall( "GetGUIThreadInfo", "uint", threadWnd, "UPtr", GuiThreadInfo.ptr ) 143 | return 0 144 | return NumGet( GuiThreadInfo, 8+A_PtrSize,"UPtr") ; Retrieve the hwndFocus field from the struct. 145 | } 146 | Static GetPixelInfo( &DIB ) { 147 | ;~ typedef struct tagBITMAPINFOHEADER { 148 | ;~ DWORD biSize; 0 149 | ;~ LONG biWidth; 4 150 | ;~ LONG biHeight; 8 151 | ;~ WORD biPlanes; 12 152 | ;~ WORD biBitCount; 14 153 | ;~ DWORD biCompression; 16 154 | ;~ DWORD biSizeImage; 20 155 | ;~ LONG biXPelsPerMeter; 24 156 | ;~ LONG biYPelsPerMeter; 28 157 | ;~ DWORD biClrUsed; 32 158 | ;~ DWORD biClrImportant; 36 159 | 160 | bmi := DIB.ptr ;BITMAPINFOHEADER pointer from DIB 161 | biSize := numget( bmi+0, 0, "UInt" ) 162 | ;~ return bmi + biSize 163 | biSizeImage := numget( bmi+0, 20, "UInt" ) 164 | biBitCount := numget( bmi+0, 14, "UShort" ) 165 | if ( biSizeImage == 0 ) 166 | { 167 | biWidth := numget( bmi+0, 4, "UInt" ) 168 | biHeight := numget( bmi+0, 8, "UInt" ) 169 | biSizeImage := (((( biWidth * biBitCount + 31 ) & ~31 ) >> 3 ) * biHeight ) 170 | numput( "UInt", biSizeImage, bmi+0, 20 ) 171 | } 172 | p := numget( bmi+0, 32, "UInt" ) ;biClrUsed 173 | if ( p == 0 && biBitCount <= 8 ) 174 | p := 1 << biBitCount 175 | p := p * 4 + biSize + bmi 176 | return p 177 | } 178 | Static Gdip_Startup() { 179 | if !DllCall( "GetModuleHandleW", "Wstr", "gdiplus", "UPtr" ) 180 | DllCall( "LoadLibraryW", "Wstr", "gdiplus", "UPtr" ) 181 | 182 | GdiplusStartupInput := Buffer( 3*A_PtrSize, 0), NumPut("UInt",1,GdiplusStartupInput ,0) ; GdiplusVersion = 1 183 | DllCall("gdiplus\GdiplusStartup", "Ptr*", &pToken:=0, "Ptr", GdiplusStartupInput.ptr, "Ptr", 0) 184 | return pToken 185 | } 186 | Static Gdip_Shutdown(pToken) { 187 | DllCall("gdiplus\GdiplusShutdown", "Ptr", pToken) 188 | if hModule := DllCall( "GetModuleHandleW", "Wstr", "gdiplus", "UPtr" ) 189 | DllCall("FreeLibrary", "Ptr", hModule) 190 | return 0 191 | } 192 | Static StrSplit(str,delim,omit := "") { 193 | if (strlen(delim) > 1) 194 | { 195 | ;StringReplace,str,str,% delim,ƒ,1 ;■¶╬ 196 | str := StrReplace(str, delim, Chr(402)) ; "ƒ" = 402 197 | delim := Chr(402) 198 | } 199 | ra := Array() 200 | loop parse str, delim, omit 201 | if (A_LoopField != "") 202 | ra.Push(A_LoopField) 203 | return ra 204 | } 205 | Static RemoveDubls( objArray ) { 206 | while True 207 | { 208 | nodubls := 1 209 | tempArr := Map() 210 | for i,val in objArray 211 | { 212 | if tempArr.has( val ) 213 | { 214 | nodubls := 0 215 | objArray.RemoveAt( i ) 216 | break 217 | } 218 | tempArr[ val ] := 1 219 | } 220 | if nodubls 221 | break 222 | } 223 | return objArray 224 | } 225 | Static RegisterClipboardFormat( fmtName ) { 226 | return DllCall( "RegisterClipboardFormat", "str", fmtName ) 227 | } 228 | Static GetOpenClipboardWindow() { 229 | return DllCall( "GetOpenClipboardWindow" ) 230 | } 231 | Static IsClipboardFormatAvailable( iFmt ) { 232 | return DllCall( "IsClipboardFormatAvailable", "UInt", iFmt ) 233 | } 234 | Static GetImageEncodersSize( &numEncoders, &size ) { 235 | return DllCall( "gdiplus\GdipGetImageEncodersSize", "Uint*", &numEncoders:=0, "UInt*", &size:=0 ) 236 | } 237 | Static GetImageEncoders( numEncoders, size, pImageCodecInfo ) { 238 | return DllCall( "gdiplus\GdipGetImageEncoders", "Uint", numEncoders, "UInt", size, "Ptr", pImageCodecInfo ) 239 | } 240 | Static GetEncoderClsid( format, &CLSID ) { 241 | ;format should be the following 242 | ;~ bmp 243 | ;~ jpeg 244 | ;~ gif 245 | ;~ tiff 246 | ;~ png 247 | if !format 248 | return 0 249 | format := "image/" format 250 | this.GetImageEncodersSize( &num, &size ) 251 | if ( size = 0 ) 252 | return 0 253 | ImageCodecInfo := Buffer( size, 0 ) 254 | this.GetImageEncoders( num, size, ImageCodecInfo.ptr ) 255 | loop num 256 | { 257 | pici := ImageCodecInfo.ptr + ( 48+7*A_PtrSize )*(A_Index-1) 258 | pMime := NumGet( pici+0, 32+4*A_PtrSize, "UPtr" ) 259 | MimeType := StrGet( pMime, "UTF-16") 260 | if ( MimeType = format ) 261 | { 262 | CLSID := Buffer( 16, 0 ) 263 | this.memcopy( CLSID.ptr, pici, 16 ) 264 | return 1 265 | } 266 | } 267 | return 0 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /__Example.ahk: -------------------------------------------------------------------------------- 1 | ; AHK v2 2 | 3 | #Include WinClipAPI.ahk 4 | #Include WinClip.ahk 5 | 6 | If FileExist("clip.txt") 7 | FileDelete "clip.txt" 8 | 9 | wc := WinClip() 10 | 11 | 12 | msgbox "copy some text on clipboard" 13 | msgbox text := wc.GetText() 14 | 15 | 16 | msgbox "copy some SMALL text piece from browser" 17 | msgbox html := wc.GetHTML() 18 | 19 | 20 | msgbox "copy some picture" 21 | hBitmap := wc.GetBitmap() 22 | If hBitmap { 23 | g := Gui() 24 | pic := g.Add("Picture", "+0xE") ; SS_BITMAP 25 | SendMessage( STM_SETIMAGE := 0x0172, IMAGE_BITMAP := 0, hBitmap, pic.hwnd) 26 | DllCall("DeleteObject", "Ptr", hBitmap ) 27 | g.Show("w1000 h700") 28 | } 29 | 30 | 31 | msgbox "copy few files from explorer window" 32 | msgbox fileslist := wc.GetFiles() 33 | 34 | 35 | obj := inputbox("Enter text you want to put on clipboard","Input Something") 36 | if obj.value 37 | { 38 | wc.Clear() 39 | wc.SetText( obj.value ) 40 | } 41 | msgbox text := wc.GetText() 42 | 43 | 44 | obj := inputbox("Enter text you want to APPEND to the one currently on clipboard", "Input Something") 45 | if obj.value 46 | wc.AppendText( obj.value ) 47 | msgbox text := wc.GetText() 48 | 49 | 50 | obj := inputbox("Enter path to the picture you want to place on clipboard ( without quotes )","Input path to Picture") 51 | if obj.value 52 | { 53 | wc.Clear() 54 | wc.SetBitmap( Trim(obj.value,Chr(34)) ) 55 | msgbox "the picture should be on clipboard now" 56 | } 57 | 58 | 59 | msgbox "copy some data to clipboard" 60 | msgbox "All clipboard data has been saved to clip.txt`nSize: " wc.Save( "clip.txt" ) 61 | 62 | 63 | wc.Clear() 64 | msgbox "clipboard should now be empty`r`n`r`n" 65 | . "ClipboardAll size: " ClipboardAll().size 66 | 67 | 68 | bytes := wc.Load( "clip.txt" ) 69 | msgbox bytes " bytes loaded from 'clip.txt' file to clipboard" 70 | 71 | 72 | obj := inputbox("Enter some text you want to place on clipboard as HTML" 73 | ,"Html to clipboard","w300 h200" 74 | ,"link") 75 | if obj.value 76 | { 77 | wc.Clear() 78 | wc.SetHTML( obj.value ) 79 | msgbox "html data should be on clipboard" 80 | } 81 | 82 | If FileExist("clip.txt") 83 | FileDelete "clip.txt" --------------------------------------------------------------------------------