/WinClip.ahk

https://github.com/Binocular222/Autohotkey-Insert-Symbol · AutoHotKey · 1052 lines · 962 code · 78 blank · 12 comment · 152 complexity · 64feebdc6fa269268de9f8b1c285a56a MD5 · raw file

  1. class WinClip extends WinClip_base
  2. {
  3. __New()
  4. {
  5. this.isinstance := 1
  6. this.allData := ""
  7. }
  8. _toclipboard( ByRef data, size )
  9. {
  10. if !WinClipAPI.OpenClipboard()
  11. return 0
  12. offset := 0
  13. lastPartOffset := 0
  14. WinClipAPI.EmptyClipboard()
  15. while ( offset < size )
  16. {
  17. if !( fmt := NumGet( data, offset, "UInt" ) )
  18. break
  19. offset += 4
  20. if !( dataSize := NumGet( data, offset, "UInt" ) )
  21. break
  22. offset += 4
  23. if ( ( offset + dataSize ) > size )
  24. break
  25. if !( pData := WinClipAPI.GlobalLock( WinClipAPI.GlobalAlloc( 0x0042, dataSize ) ) )
  26. {
  27. offset += dataSize
  28. continue
  29. }
  30. WinClipAPI.memcopy( pData, &data + offset, dataSize )
  31. if ( fmt == this.ClipboardFormats.CF_ENHMETAFILE )
  32. pClipData := WinClipAPI.SetEnhMetaFileBits( pData, dataSize )
  33. else
  34. pClipData := pData
  35. if !pClipData
  36. continue
  37. WinClipAPI.SetClipboardData( fmt, pClipData )
  38. if ( fmt == this.ClipboardFormats.CF_ENHMETAFILE )
  39. WinClipAPI.DeleteEnhMetaFile( pClipData )
  40. WinClipAPI.GlobalUnlock( pData )
  41. offset += dataSize
  42. lastPartOffset := offset
  43. }
  44. WinClipAPI.CloseClipboard()
  45. return lastPartOffset
  46. }
  47. _fromclipboard( ByRef clipData )
  48. {
  49. if !WinClipAPI.OpenClipboard()
  50. return 0
  51. nextformat := 0
  52. objFormats := object()
  53. clipSize := 0
  54. formatsNum := 0
  55. while ( nextformat := WinClipAPI.EnumClipboardFormats( nextformat ) )
  56. {
  57. if this.skipFormats.hasKey( nextformat )
  58. continue
  59. if ( dataHandle := WinClipAPI.GetClipboardData( nextformat ) )
  60. {
  61. pObjPtr := 0, nObjSize := 0
  62. if ( nextFormat == this.ClipboardFormats.CF_ENHMETAFILE )
  63. {
  64. if ( bufSize := WinClipAPI.GetEnhMetaFileBits( dataHandle, hemfBuf ) )
  65. pObjPtr := &hemfBuf, nObjSize := bufSize
  66. }
  67. else if ( nSize := WinClipAPI.GlobalSize( WinClipAPI.GlobalLock( dataHandle ) ) )
  68. pObjPtr := dataHandle, nObjSize := nSize
  69. else
  70. continue
  71. if !( pObjPtr && nObjSize )
  72. continue
  73. objFormats[ nextformat ] := { handle : pObjPtr, size : nObjSize }
  74. clipSize += nObjSize
  75. formatsNum++
  76. }
  77. }
  78. structSize := formatsNum*( 4 + 4 ) + clipSize ;allocating 4 bytes for format ID and 4 for data size
  79. if !structSize
  80. return 0
  81. VarSetCapacity( clipData, structSize, 0 )
  82. ; array in form of:
  83. ; format UInt
  84. ; dataSize UInt
  85. ; data Byte[]
  86. offset := 0
  87. for fmt, params in objFormats
  88. {
  89. NumPut( fmt, &clipData, offset, "UInt" )
  90. offset += 4
  91. NumPut( params.size, &clipData, offset, "UInt" )
  92. offset += 4
  93. WinClipAPI.memcopy( &clipData + offset, params.handle, params.size )
  94. offset += params.size
  95. WinClipAPI.GlobalUnlock( params.handle )
  96. }
  97. WinClipAPI.CloseClipboard()
  98. return structSize
  99. }
  100. _IsInstance( funcName )
  101. {
  102. if !this.isinstance
  103. {
  104. throw Exception( "Error in '" funcName "':`nInstantiate the object first to use this method!", -1 )
  105. return 0
  106. }
  107. return 1
  108. }
  109. _loadFile( filePath, ByRef Data )
  110. {
  111. f := FileOpen( filePath, "r","CP0" )
  112. if !IsObject( f )
  113. return 0
  114. f.Pos := 0
  115. dataSize := f.RawRead( Data, f.Length )
  116. f.close()
  117. return dataSize
  118. }
  119. _saveFile( filepath, byRef data, size )
  120. {
  121. f := FileOpen( filepath, "w","CP0" )
  122. bytes := f.RawWrite( &data, size )
  123. f.close()
  124. return bytes
  125. }
  126. _setClipData( ByRef data, size )
  127. {
  128. if !size
  129. return 0
  130. if !ObjSetCapacity( this, "allData", size )
  131. return 0
  132. if !( pData := ObjGetAddress( this, "allData" ) )
  133. return 0
  134. WinClipAPI.memcopy( pData, &data, size )
  135. return size
  136. }
  137. _getClipData( ByRef data )
  138. {
  139. if !( clipSize := ObjGetCapacity( this, "allData" ) )
  140. return 0
  141. if !( pData := ObjGetAddress( this, "allData" ) )
  142. return 0
  143. VarSetCapacity( data, clipSize, 0 )
  144. WinClipAPI.memcopy( &data, pData, clipSize )
  145. return clipSize
  146. }
  147. __Delete()
  148. {
  149. ObjSetCapacity( this, "allData", 0 )
  150. return
  151. }
  152. _parseClipboardData( ByRef data, size )
  153. {
  154. offset := 0
  155. formats := object()
  156. while ( offset < size )
  157. {
  158. if !( fmt := NumGet( data, offset, "UInt" ) )
  159. break
  160. offset += 4
  161. if !( dataSize := NumGet( data, offset, "UInt" ) )
  162. break
  163. offset += 4
  164. if ( ( offset + dataSize ) > size )
  165. break
  166. params := { name : this._getFormatName( fmt ), size : dataSize }
  167. ObjSetCapacity( params, "buffer", dataSize )
  168. pBuf := ObjGetAddress( params, "buffer" )
  169. WinClipAPI.memcopy( pBuf, &data + offset, dataSize )
  170. formats[ fmt ] := params
  171. offset += dataSize
  172. }
  173. return formats
  174. }
  175. _compileClipData( ByRef out_data, objClip )
  176. {
  177. if !IsObject( objClip )
  178. return 0
  179. ;calculating required data size
  180. clipSize := 0
  181. for fmt, params in objClip
  182. clipSize += 8 + params.size
  183. VarSetCapacity( out_data, clipSize, 0 )
  184. offset := 0
  185. for fmt, params in objClip
  186. {
  187. NumPut( fmt, out_data, offset, "UInt" )
  188. offset += 4
  189. NumPut( params.size, out_data, offset, "UInt" )
  190. offset += 4
  191. WinClipAPI.memcopy( &out_data + offset, ObjGetAddress( params, "buffer" ), params.size )
  192. offset += params.size
  193. }
  194. return clipSize
  195. }
  196. GetFormats()
  197. {
  198. if !( clipSize := this._fromclipboard( clipData ) )
  199. return 0
  200. return this._parseClipboardData( clipData, clipSize )
  201. }
  202. iGetFormats()
  203. {
  204. this._IsInstance( A_ThisFunc )
  205. if !( clipSize := this._getClipData( clipData ) )
  206. return 0
  207. return this._parseClipboardData( clipData, clipSize )
  208. }
  209. Snap( ByRef data )
  210. {
  211. return this._fromclipboard( data )
  212. }
  213. iSnap()
  214. {
  215. this._IsInstance( A_ThisFunc )
  216. if !( dataSize := this._fromclipboard( clipData ) )
  217. return 0
  218. return this._setClipData( clipData, dataSize )
  219. }
  220. Restore( ByRef clipData )
  221. {
  222. clipSize := VarSetCapacity( clipData )
  223. return this._toclipboard( clipData, clipSize )
  224. }
  225. iRestore()
  226. {
  227. this._IsInstance( A_ThisFunc )
  228. if !( clipSize := this._getClipData( clipData ) )
  229. return 0
  230. return this._toclipboard( clipData, clipSize )
  231. }
  232. Save( filePath )
  233. {
  234. if !( size := this._fromclipboard( data ) )
  235. return 0
  236. return this._saveFile( filePath, data, size )
  237. }
  238. iSave( filePath )
  239. {
  240. this._IsInstance( A_ThisFunc )
  241. if !( clipSize := this._getClipData( clipData ) )
  242. return 0
  243. return this._saveFile( filePath, clipData, clipSize )
  244. }
  245. Load( filePath )
  246. {
  247. if !( dataSize := this._loadFile( filePath, dataBuf ) )
  248. return 0
  249. return this._toclipboard( dataBuf, dataSize )
  250. }
  251. iLoad( filePath )
  252. {
  253. this._IsInstance( A_ThisFunc )
  254. if !( dataSize := this._loadFile( filePath, dataBuf ) )
  255. return 0
  256. return this._setClipData( dataBuf, dataSize )
  257. }
  258. Clear()
  259. {
  260. if !WinClipAPI.OpenClipboard()
  261. return 0
  262. WinClipAPI.EmptyClipboard()
  263. WinClipAPI.CloseClipboard()
  264. return 1
  265. }
  266. iClear()
  267. {
  268. this._IsInstance( A_ThisFunc )
  269. ObjSetCapacity( this, "allData", 0 )
  270. }
  271. Copy( timeout = 1, method = 1 )
  272. {
  273. this.Snap( data )
  274. this.Clear() ;clearing the clipboard
  275. if( method = 1 )
  276. SendInput, ^{Ins}
  277. else
  278. SendInput, ^{vk43sc02E} ;ctrl+c
  279. ClipWait,% timeout, 1
  280. if ( ret := this._isClipEmpty() )
  281. this.Restore( data )
  282. return !ret
  283. }
  284. iCopy( timeout = 1, method = 1 )
  285. {
  286. this._IsInstance( A_ThisFunc )
  287. this.Snap( data )
  288. this.Clear() ;clearing the clipboard
  289. if( method = 1 )
  290. SendInput, ^{Ins}
  291. else
  292. SendInput, ^{vk43sc02E} ;ctrl+c
  293. ClipWait,% timeout, 1
  294. bytesCopied := 0
  295. if !this._isClipEmpty()
  296. {
  297. this.iClear() ;clearing the variable containing the clipboard data
  298. bytesCopied := this.iSnap()
  299. }
  300. this.Restore( data )
  301. return bytesCopied
  302. }
  303. Paste( plainText = "", method = 1 )
  304. {
  305. ret := 0
  306. if ( plainText != "" )
  307. {
  308. this.Snap( data )
  309. this.Clear()
  310. ret := this.SetText( plainText )
  311. }
  312. if( method = 1 )
  313. SendInput, +{Ins}
  314. else
  315. SendInput, ^{vk56sc02F} ;ctrl+v
  316. this._waitClipReady( 3000 )
  317. if ( plainText != "" )
  318. {
  319. this.Restore( data )
  320. }
  321. else
  322. ret := !this._isClipEmpty()
  323. return ret
  324. }
  325. iPaste( method = 1 )
  326. {
  327. this._IsInstance( A_ThisFunc )
  328. this.Snap( data )
  329. if !( bytesRestored := this.iRestore() )
  330. return 0
  331. if( method = 1 )
  332. SendInput, +{Ins}
  333. else
  334. SendInput, ^{vk56sc02F} ;ctrl+v
  335. this._waitClipReady( 3000 )
  336. this.Restore( data )
  337. return bytesRestored
  338. }
  339. IsEmpty()
  340. {
  341. return this._isClipEmpty()
  342. }
  343. iIsEmpty()
  344. {
  345. return !this.iGetSize()
  346. }
  347. _isClipEmpty()
  348. {
  349. return !WinClipAPI.CountClipboardFormats()
  350. }
  351. _waitClipReady( timeout = 10000 )
  352. {
  353. start_time := A_TickCount
  354. sleep 100
  355. while ( WinClipAPI.GetOpenClipboardWindow() && ( A_TickCount - start_time < timeout ) )
  356. sleep 100
  357. }
  358. iSetText( textData )
  359. {
  360. if ( textData = "" )
  361. return 0
  362. this._IsInstance( A_ThisFunc )
  363. clipSize := this._getClipData( clipData )
  364. if !( clipSize := this._appendText( clipData, clipSize, textData, 1 ) )
  365. return 0
  366. return this._setClipData( clipData, clipSize )
  367. }
  368. SetText( textData )
  369. {
  370. if ( textData = "" )
  371. return 0
  372. clipSize := this._fromclipboard( clipData )
  373. if !( clipSize := this._appendText( clipData, clipSize, textData, 1 ) )
  374. return 0
  375. return this._toclipboard( clipData, clipSize )
  376. }
  377. GetRTF()
  378. {
  379. if !( clipSize := this._fromclipboard( clipData ) )
  380. return ""
  381. if !( out_size := this._getFormatData( out_data, clipData, clipSize, "Rich Text Format" ) )
  382. return ""
  383. return strget( &out_data, out_size, "CP0" )
  384. }
  385. iGetRTF()
  386. {
  387. this._IsInstance( A_ThisFunc )
  388. if !( clipSize := this._getClipData( clipData ) )
  389. return ""
  390. if !( out_size := this._getFormatData( out_data, clipData, clipSize, "Rich Text Format" ) )
  391. return ""
  392. return strget( &out_data, out_size, "CP0" )
  393. }
  394. SetRTF( textData )
  395. {
  396. if ( textData = "" )
  397. return 0
  398. clipSize := this._fromclipboard( clipData )
  399. if !( clipSize := this._setRTF( clipData, clipSize, textData ) )
  400. return 0
  401. return this._toclipboard( clipData, clipSize )
  402. }
  403. iSetRTF( textData )
  404. {
  405. if ( textData = "" )
  406. return 0
  407. this._IsInstance( A_ThisFunc )
  408. clipSize := this._getClipData( clipData )
  409. if !( clipSize := this._setRTF( clipData, clipSize, textData ) )
  410. return 0
  411. return this._setClipData( clipData, clipSize )
  412. }
  413. _setRTF( ByRef clipData, clipSize, textData )
  414. {
  415. objFormats := this._parseClipboardData( clipData, clipSize )
  416. uFmt := WinClipAPI.RegisterClipboardFormat( "Rich Text Format" )
  417. objFormats[ uFmt ] := object()
  418. sLen := StrLen( textData )
  419. ObjSetCapacity( objFormats[ uFmt ], "buffer", sLen )
  420. StrPut( textData, ObjGetAddress( objFormats[ uFmt ], "buffer" ), sLen, "CP0" )
  421. objFormats[ uFmt ].size := sLen
  422. return this._compileClipData( clipData, objFormats )
  423. }
  424. iAppendText( textData )
  425. {
  426. if ( textData = "" )
  427. return 0
  428. this._IsInstance( A_ThisFunc )
  429. clipSize := this._getClipData( clipData )
  430. if !( clipSize := this._appendText( clipData, clipSize, textData ) )
  431. return 0
  432. return this._setClipData( clipData, clipSize )
  433. }
  434. AppendText( textData )
  435. {
  436. if ( textData = "" )
  437. return 0
  438. clipSize := this._fromclipboard( clipData )
  439. if !( clipSize := this._appendText( clipData, clipSize, textData ) )
  440. return 0
  441. return this._toclipboard( clipData, clipSize )
  442. }
  443. SetHTML( html, source = "" )
  444. {
  445. if ( html = "" )
  446. return 0
  447. clipSize := this._fromclipboard( clipData )
  448. if !( clipSize := this._setHTML( clipData, clipSize, html, source ) )
  449. return 0
  450. return this._toclipboard( clipData, clipSize )
  451. }
  452. iSetHTML( html, source = "" )
  453. {
  454. if ( html = "" )
  455. return 0
  456. this._IsInstance( A_ThisFunc )
  457. clipSize := this._getClipData( clipData )
  458. if !( clipSize := this._setHTML( clipData, clipSize, html, source ) )
  459. return 0
  460. return this._setClipData( clipData, clipSize )
  461. }
  462. _calcHTMLLen( num )
  463. {
  464. while ( StrLen( num ) < 10 )
  465. num := "0" . num
  466. return num
  467. }
  468. _setHTML( ByRef clipData, clipSize, htmlData, source )
  469. {
  470. objFormats := this._parseClipboardData( clipData, clipSize )
  471. uFmt := WinClipAPI.RegisterClipboardFormat( "HTML Format" )
  472. objFormats[ uFmt ] := object()
  473. encoding := "UTF-8"
  474. htmlLen := StrPut( htmlData, encoding ) - 1 ;substract null
  475. srcLen := 2 + 10 + StrPut( source, encoding ) - 1 ;substract null
  476. StartHTML := this._calcHTMLLen( 105 + srcLen )
  477. EndHTML := this._calcHTMLLen( StartHTML + htmlLen + 76 )
  478. StartFragment := this._calcHTMLLen( StartHTML + 38 )
  479. EndFragment := this._calcHTMLLen( StartFragment + htmlLen )
  480. html =
  481. ( Join`r`n
  482. Version:0.9
  483. StartHTML:%StartHTML%
  484. EndHTML:%EndHTML%
  485. StartFragment:%StartFragment%
  486. EndFragment:%EndFragment%
  487. SourceURL:%source%
  488. <html>
  489. <body>
  490. <!--StartFragment-->
  491. %htmlData%
  492. <!--EndFragment-->
  493. </body>
  494. </html>
  495. )
  496. sLen := StrPut( html, encoding )
  497. ObjSetCapacity( objFormats[ uFmt ], "buffer", sLen )
  498. StrPut( html, ObjGetAddress( objFormats[ uFmt ], "buffer" ), sLen, encoding )
  499. objFormats[ uFmt ].size := sLen
  500. return this._compileClipData( clipData, objFormats )
  501. }
  502. _appendText( ByRef clipData, clipSize, textData, IsSet = 0 )
  503. {
  504. objFormats := this._parseClipboardData( clipData, clipSize )
  505. uFmt := this.ClipboardFormats.CF_UNICODETEXT
  506. str := ""
  507. if ( objFormats.haskey( uFmt ) && !IsSet )
  508. str := strget( ObjGetAddress( objFormats[ uFmt ], "buffer" ), "UTF-16" )
  509. else
  510. objFormats[ uFmt ] := object()
  511. str .= textData
  512. sLen := ( StrLen( str ) + 1 ) * 2
  513. ObjSetCapacity( objFormats[ uFmt ], "buffer", sLen )
  514. StrPut( str, ObjGetAddress( objFormats[ uFmt ], "buffer" ), sLen, "UTF-16" )
  515. objFormats[ uFmt ].size := sLen
  516. return this._compileClipData( clipData, objFormats )
  517. }
  518. _getFiles( pDROPFILES )
  519. {
  520. fWide := numget( pDROPFILES + 0, 16, "uchar" ) ;getting fWide value from DROPFILES struct
  521. pFiles := numget( pDROPFILES + 0, 0, "UInt" ) + pDROPFILES ;getting address of files list
  522. list := ""
  523. while numget( pFiles + 0, 0, fWide ? "UShort" : "UChar" )
  524. {
  525. lastPath := strget( pFiles+0, fWide ? "UTF-16" : "CP0" )
  526. list .= ( list ? "`n" : "" ) lastPath
  527. pFiles += ( StrLen( lastPath ) + 1 ) * ( fWide ? 2 : 1 )
  528. }
  529. return list
  530. }
  531. _setFiles( ByRef clipData, clipSize, files, append = 0, isCut = 0 )
  532. {
  533. objFormats := this._parseClipboardData( clipData, clipSize )
  534. uFmt := this.ClipboardFormats.CF_HDROP
  535. if ( append && objFormats.haskey( uFmt ) )
  536. prevList := this._getFiles( ObjGetAddress( objFormats[ uFmt ], "buffer" ) ) "`n"
  537. objFiles := WinClipAPI.StrSplit( prevList . files, "`n", A_Space A_Tab )
  538. objFiles := WinClipAPI.RemoveDubls( objFiles )
  539. if !objFiles.MaxIndex()
  540. return 0
  541. objFormats[ uFmt ] := object()
  542. DROP_size := 20 + 2
  543. for i,str in objFiles
  544. DROP_size += ( StrLen( str ) + 1 ) * 2
  545. VarSetCapacity( DROPFILES, DROP_size, 0 )
  546. NumPut( 20, DROPFILES, 0, "UInt" ) ;offset
  547. NumPut( 1, DROPFILES, 16, "uchar" ) ;NumPut( 20, DROPFILES, 0, "UInt" )
  548. offset := &DROPFILES + 20
  549. for i,str in objFiles
  550. {
  551. StrPut( str, offset, "UTF-16" )
  552. offset += ( StrLen( str ) + 1 ) * 2
  553. }
  554. ObjSetCapacity( objFormats[ uFmt ], "buffer", DROP_size )
  555. WinClipAPI.memcopy( ObjGetAddress( objFormats[ uFmt ], "buffer" ), &DROPFILES, DROP_size )
  556. objFormats[ uFmt ].size := DROP_size
  557. prefFmt := WinClipAPI.RegisterClipboardFormat( "Preferred DropEffect" )
  558. objFormats[ prefFmt ] := { size : 4 }
  559. ObjSetCapacity( objFormats[ prefFmt ], "buffer", 4 )
  560. NumPut( isCut ? 2 : 5, ObjGetAddress( objFormats[ prefFmt ], "buffer" ), 0 "UInt" )
  561. return this._compileClipData( clipData, objFormats )
  562. }
  563. SetFiles( files, isCut = 0 )
  564. {
  565. if ( files = "" )
  566. return 0
  567. clipSize := this._fromclipboard( clipData )
  568. if !( clipSize := this._setFiles( clipData, clipSize, files, 0, isCut ) )
  569. return 0
  570. return this._toclipboard( clipData, clipSize )
  571. }
  572. iSetFiles( files, isCut = 0 )
  573. {
  574. this._IsInstance( A_ThisFunc )
  575. if ( files = "" )
  576. return 0
  577. clipSize := this._getClipData( clipData )
  578. if !( clipSize := this._setFiles( clipData, clipSize, files, 0, isCut ) )
  579. return 0
  580. return this._setClipData( clipData, clipSize )
  581. }
  582. AppendFiles( files, isCut = 0 )
  583. {
  584. if ( files = "" )
  585. return 0
  586. clipSize := this._fromclipboard( clipData )
  587. if !( clipSize := this._setFiles( clipData, clipSize, files, 1, isCut ) )
  588. return 0
  589. return this._toclipboard( clipData, clipSize )
  590. }
  591. iAppendFiles( files, isCut = 0 )
  592. {
  593. this._IsInstance( A_ThisFunc )
  594. if ( files = "" )
  595. return 0
  596. clipSize := this._getClipData( clipData )
  597. if !( clipSize := this._setFiles( clipData, clipSize, files, 1, isCut ) )
  598. return 0
  599. return this._setClipData( clipData, clipSize )
  600. }
  601. GetFiles()
  602. {
  603. if !( clipSize := this._fromclipboard( clipData ) )
  604. return ""
  605. if !( out_size := this._getFormatData( out_data, clipData, clipSize, this.ClipboardFormats.CF_HDROP ) )
  606. return ""
  607. return this._getFiles( &out_data )
  608. }
  609. iGetFiles()
  610. {
  611. this._IsInstance( A_ThisFunc )
  612. if !( clipSize := this._getClipData( clipData ) )
  613. return ""
  614. if !( out_size := this._getFormatData( out_data, clipData, clipSize, this.ClipboardFormats.CF_HDROP ) )
  615. return ""
  616. return this._getFiles( &out_data )
  617. }
  618. _getFormatData( ByRef out_data, ByRef data, size, needleFormat )
  619. {
  620. needleFormat := WinClipAPI.IsInteger( needleFormat ) ? needleFormat : WinClipAPI.RegisterClipboardFormat( needleFormat )
  621. if !needleFormat
  622. return 0
  623. offset := 0
  624. while ( offset < size )
  625. {
  626. if !( fmt := NumGet( data, offset, "UInt" ) )
  627. break
  628. offset += 4
  629. if !( dataSize := NumGet( data, offset, "UInt" ) )
  630. break
  631. offset += 4
  632. if ( fmt == needleFormat )
  633. {
  634. VarSetCapacity( out_data, dataSize, 0 )
  635. WinClipAPI.memcopy( &out_data, &data + offset, dataSize )
  636. return dataSize
  637. }
  638. offset += dataSize
  639. }
  640. return 0
  641. }
  642. _DIBtoHBITMAP( ByRef dibData )
  643. {
  644. ;http://ebersys.blogspot.com/2009/06/how-to-convert-dib-to-bitmap.html
  645. pPix := WinClipAPI.GetPixelInfo( dibData )
  646. gdip_token := WinClipAPI.Gdip_Startup()
  647. DllCall("gdiplus\GdipCreateBitmapFromGdiDib", "Ptr", &dibData, "Ptr", pPix, "Ptr*", pBitmap )
  648. DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "Ptr*", hBitmap, "int", 0xffffffff )
  649. DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap)
  650. WinClipAPI.Gdip_Shutdown( gdip_token )
  651. return hBitmap
  652. }
  653. GetBitmap()
  654. {
  655. if !( clipSize := this._fromclipboard( clipData ) )
  656. return ""
  657. if !( out_size := this._getFormatData( out_data, clipData, clipSize, this.ClipboardFormats.CF_DIB ) )
  658. return ""
  659. return this._DIBtoHBITMAP( out_data )
  660. }
  661. iGetBitmap()
  662. {
  663. this._IsInstance( A_ThisFunc )
  664. if !( clipSize := this._getClipData( clipData ) )
  665. return ""
  666. if !( out_size := this._getFormatData( out_data, clipData, clipSize, this.ClipboardFormats.CF_DIB ) )
  667. return ""
  668. return this._DIBtoHBITMAP( out_data )
  669. }
  670. _BITMAPtoDIB( bitmap, ByRef DIB )
  671. {
  672. if !bitmap
  673. return 0
  674. if !WinClipAPI.IsInteger( bitmap )
  675. {
  676. gdip_token := WinClipAPI.Gdip_Startup()
  677. DllCall("gdiplus\GdipCreateBitmapFromFileICM", "wstr", bitmap, "Ptr*", pBitmap )
  678. DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "Ptr*", hBitmap, "int", 0xffffffff )
  679. DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap)
  680. WinClipAPI.Gdip_Shutdown( gdip_token )
  681. bmMade := 1
  682. }
  683. else
  684. hBitmap := bitmap, bmMade := 0
  685. if !hBitmap
  686. return 0
  687. ;http://www.codeguru.com/Cpp/G-M/bitmap/article.php/c1765
  688. if !( hdc := DllCall( "GetDC", "Ptr", 0 ) )
  689. goto, _BITMAPtoDIB_cleanup
  690. hPal := DllCall( "GetStockObject", "UInt", 15 ) ;DEFAULT_PALLETE
  691. hPal := DllCall( "SelectPalette", "ptr", hdc, "ptr", hPal, "Uint", 0 )
  692. DllCall( "RealizePalette", "ptr", hdc )
  693. size := DllCall( "GetObject", "Ptr", hBitmap, "Uint", 0, "ptr", 0 )
  694. VarSetCapacity( bm, size, 0 )
  695. DllCall( "GetObject", "Ptr", hBitmap, "Uint", size, "ptr", &bm )
  696. biBitCount := NumGet( bm, 16, "UShort" )*NumGet( bm, 18, "UShort" )
  697. nColors := (1 << biBitCount)
  698. if ( nColors > 256 )
  699. nColors := 0
  700. bmiLen := 40 + nColors * 4
  701. VarSetCapacity( bmi, bmiLen, 0 )
  702. ;BITMAPINFOHEADER initialization
  703. NumPut( 40, bmi, 0, "Uint" )
  704. NumPut( NumGet( bm, 4, "Uint" ), bmi, 4, "Uint" ) ;width
  705. NumPut( biHeight := NumGet( bm, 8, "Uint" ), bmi, 8, "Uint" ) ;height
  706. NumPut( 1, bmi, 12, "UShort" )
  707. NumPut( biBitCount, bmi, 14, "UShort" )
  708. NumPut( 0, bmi, 16, "UInt" ) ;compression must be BI_RGB
  709. ; Get BITMAPINFO.
  710. if !DllCall("GetDIBits"
  711. ,"ptr",hdc
  712. ,"ptr",hBitmap
  713. ,"uint",0
  714. ,"uint",biHeight
  715. ,"ptr",0 ;lpvBits
  716. ,"ptr",&bmi ;lpbi
  717. ,"uint",0) ;DIB_RGB_COLORS
  718. goto, _BITMAPtoDIB_cleanup
  719. biSizeImage := NumGet( &bmi, 20, "UInt" )
  720. if ( biSizeImage = 0 )
  721. {
  722. biBitCount := numget( &bmi, 14, "UShort" )
  723. biWidth := numget( &bmi, 4, "UInt" )
  724. biHeight := numget( &bmi, 8, "UInt" )
  725. biSizeImage := (((( biWidth * biBitCount + 31 ) & ~31 ) >> 3 ) * biHeight )
  726. ;~ dwCompression := numget( bmi, 16, "UInt" )
  727. ;~ if ( dwCompression != 0 ) ;BI_RGB
  728. ;~ biSizeImage := ( biSizeImage * 3 ) / 2
  729. numput( biSizeImage, &bmi, 20, "UInt" )
  730. }
  731. DIBLen := bmiLen + biSizeImage
  732. VarSetCapacity( DIB, DIBLen, 0 )
  733. WinClipAPI.memcopy( &DIB, &bmi, bmiLen )
  734. if !DllCall("GetDIBits"
  735. ,"ptr",hdc
  736. ,"ptr",hBitmap
  737. ,"uint",0
  738. ,"uint",biHeight
  739. ,"ptr",&DIB + bmiLen ;lpvBits
  740. ,"ptr",&DIB ;lpbi
  741. ,"uint",0) ;DIB_RGB_COLORS
  742. goto, _BITMAPtoDIB_cleanup
  743. _BITMAPtoDIB_cleanup:
  744. if bmMade
  745. DllCall( "DeleteObject", "ptr", hBitmap )
  746. DllCall( "SelectPalette", "ptr", hdc, "ptr", hPal, "Uint", 0 )
  747. DllCall( "RealizePalette", "ptr", hdc )
  748. DllCall("ReleaseDC","ptr",hdc)
  749. if ( A_ThisLabel = "_BITMAPtoDIB_cleanup" )
  750. return 0
  751. return DIBLen
  752. }
  753. _setBitmap( ByRef DIB, DIBSize, ByRef clipData, clipSize )
  754. {
  755. objFormats := this._parseClipboardData( clipData, clipSize )
  756. uFmt := this.ClipboardFormats.CF_DIB
  757. objFormats[ uFmt ] := { size : DIBSize }
  758. ObjSetCapacity( objFormats[ uFmt ], "buffer", DIBSize )
  759. WinClipAPI.memcopy( ObjGetAddress( objFormats[ uFmt ], "buffer" ), &DIB, DIBSize )
  760. return this._compileClipData( clipData, objFormats )
  761. }
  762. SetBitmap( bitmap )
  763. {
  764. if ( DIBSize := this._BITMAPtoDIB( bitmap, DIB ) )
  765. {
  766. clipSize := this._fromclipboard( clipData )
  767. if ( clipSize := this._setBitmap( DIB, DIBSize, clipData, clipSize ) )
  768. return this._toclipboard( clipData, clipSize )
  769. }
  770. return 0
  771. }
  772. iSetBitmap( bitmap )
  773. {
  774. this._IsInstance( A_ThisFunc )
  775. if ( DIBSize := this._BITMAPtoDIB( bitmap, DIB ) )
  776. {
  777. clipSize := this._getClipData( clipData )
  778. if ( clipSize := this._setBitmap( DIB, DIBSize, clipData, clipSize ) )
  779. return this._setClipData( clipData, clipSize )
  780. }
  781. return 0
  782. }
  783. GetText()
  784. {
  785. if !( clipSize := this._fromclipboard( clipData ) )
  786. return ""
  787. if !( out_size := this._getFormatData( out_data, clipData, clipSize, this.ClipboardFormats.CF_UNICODETEXT ) )
  788. return ""
  789. return strget( &out_data, out_size, "UTF-16" )
  790. }
  791. iGetText()
  792. {
  793. this._IsInstance( A_ThisFunc )
  794. if !( clipSize := this._getClipData( clipData ) )
  795. return ""
  796. if !( out_size := this._getFormatData( out_data, clipData, clipSize, this.ClipboardFormats.CF_UNICODETEXT ) )
  797. return ""
  798. return strget( &out_data, out_size, "UTF-16" )
  799. }
  800. GetHtml()
  801. {
  802. if !( clipSize := this._fromclipboard( clipData ) )
  803. return ""
  804. if !( out_size := this._getFormatData( out_data, clipData, clipSize, "HTML Format" ) )
  805. return ""
  806. return strget( &out_data, out_size, "CP0" )
  807. }
  808. iGetHtml()
  809. {
  810. this._IsInstance( A_ThisFunc )
  811. if !( clipSize := this._getClipData( clipData ) )
  812. return ""
  813. if !( out_size := this._getFormatData( out_data, clipData, clipSize, "HTML Format" ) )
  814. return ""
  815. return strget( &out_data, out_size, "CP0" )
  816. }
  817. _getFormatName( iformat )
  818. {
  819. if this.formatByValue.HasKey( iformat )
  820. return this.formatByValue[ iformat ]
  821. else
  822. return WinClipAPI.GetClipboardFormatName( iformat )
  823. }
  824. iGetData( ByRef Data )
  825. {
  826. this._IsInstance( A_ThisFunc )
  827. return this._getClipData( Data )
  828. }
  829. iSetData( ByRef data )
  830. {
  831. this._IsInstance( A_ThisFunc )
  832. return this._setClipData( data, VarSetCapacity( data ) )
  833. }
  834. iGetSize()
  835. {
  836. this._IsInstance( A_ThisFunc )
  837. return ObjGetCapacity( this, "alldata" )
  838. }
  839. HasFormat( fmt )
  840. {
  841. if !fmt
  842. return 0
  843. return WinClipAPI.IsClipboardFormatAvailable( WinClipAPI.IsInteger( fmt ) ? fmt
  844. : WinClipAPI.RegisterClipboardFormat( fmt ) )
  845. }
  846. iHasFormat( fmt )
  847. {
  848. this._IsInstance( A_ThisFunc )
  849. if !( clipSize := this._getClipData( clipData ) )
  850. return 0
  851. return this._hasFormat( clipData, clipSize, fmt )
  852. }
  853. _hasFormat( ByRef data, size, needleFormat )
  854. {
  855. needleFormat := WinClipAPI.IsInteger( needleFormat ) ? needleFormat
  856. : WinClipAPI.RegisterClipboardFormat( needleFormat )
  857. if !needleFormat
  858. return 0
  859. offset := 0
  860. while ( offset < size )
  861. {
  862. if !( fmt := NumGet( data, offset, "UInt" ) )
  863. break
  864. if ( fmt == needleFormat )
  865. return 1
  866. offset += 4
  867. if !( dataSize := NumGet( data, offset, "UInt" ) )
  868. break
  869. offset += 4 + dataSize
  870. }
  871. return 0
  872. }
  873. iSaveBitmap( filePath, format )
  874. {
  875. this._IsInstance( A_ThisFunc )
  876. if ( filePath = "" || format = "" )
  877. return 0
  878. if !( clipSize := this._getClipData( clipData ) )
  879. return 0
  880. if !( DIBsize := this._getFormatData( DIB, clipData, clipSize, this.ClipboardFormats.CF_DIB ) )
  881. return 0
  882. gdip_token := WinClipAPI.Gdip_Startup()
  883. if !WinClipAPI.GetEncoderClsid( format, CLSID )
  884. return 0
  885. DllCall("gdiplus\GdipCreateBitmapFromGdiDib", "Ptr", &DIB, "Ptr", WinClipAPI.GetPixelInfo( DIB ), "Ptr*", pBitmap )
  886. DllCall("gdiplus\GdipSaveImageToFile", "Ptr", pBitmap, "wstr", filePath, "Ptr", &CLSID, "Ptr", 0 )
  887. DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap)
  888. WinClipAPI.Gdip_Shutdown( gdip_token )
  889. return 1
  890. }
  891. SaveBitmap( filePath, format )
  892. {
  893. if ( filePath = "" || format = "" )
  894. return 0
  895. if !( clipSize := this._fromclipboard( clipData ) )
  896. return 0
  897. if !( DIBsize := this._getFormatData( DIB, clipData, clipSize, this.ClipboardFormats.CF_DIB ) )
  898. return 0
  899. gdip_token := WinClipAPI.Gdip_Startup()
  900. if !WinClipAPI.GetEncoderClsid( format, CLSID )
  901. return 0
  902. DllCall("gdiplus\GdipCreateBitmapFromGdiDib", "Ptr", &DIB, "Ptr", WinClipAPI.GetPixelInfo( DIB ), "Ptr*", pBitmap )
  903. DllCall("gdiplus\GdipSaveImageToFile", "Ptr", pBitmap, "wstr", filePath, "Ptr", &CLSID, "Ptr", 0 )
  904. DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap)
  905. WinClipAPI.Gdip_Shutdown( gdip_token )
  906. return 1
  907. }
  908. static ClipboardFormats := { CF_BITMAP : 2 ;A handle to a bitmap (HBITMAP).
  909. ,CF_DIB : 8 ;A memory object containing a BITMAPINFO structure followed by the bitmap bits.
  910. ,CF_DIBV5 : 17 ;A memory object containing a BITMAPV5HEADER structure followed by the bitmap color space information and the bitmap bits.
  911. ,CF_DIF : 5 ;Software Arts' Data Interchange Format.
  912. ,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.
  913. ,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.
  914. ,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.
  915. ,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.
  916. ,CF_ENHMETAFILE : 14 ;A handle to an enhanced metafile (HENHMETAFILE).
  917. ,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.
  918. ,CF_GDIOBJLAST : 0x03FF ;See CF_GDIOBJFIRST.
  919. ,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.
  920. ,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.
  921. ,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.
  922. ,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.
  923. ,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.
  924. ,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.
  925. ,CF_PENDATA : 10 ;Data for the pen extensions to the Microsoft Windows for Pen Computing.
  926. ,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.
  927. ,CF_PRIVATELAST : 0x02FF ;See CF_PRIVATEFIRST.
  928. ,CF_RIFF : 11 ;Represents audio data more complex than can be represented in a CF_WAVE standard wave format.
  929. ,CF_SYLK : 4 ;Microsoft Symbolic Link (SYLK) format.
  930. ,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.
  931. ,CF_TIFF : 6 ;Tagged-image file format.
  932. ,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.
  933. ,CF_WAVE : 12 } ;Represents audio data in one of the standard wave formats, such as 11 kHz or 22 kHz PCM.
  934. static WM_COPY := 0x301
  935. ,WM_CLEAR := 0x0303
  936. ,WM_CUT := 0x0300
  937. ,WM_PASTE := 0x0302
  938. static skipFormats := { 2 : 0 ;"CF_BITMAP"
  939. ,17 : 0 ;"CF_DIBV5"
  940. ,0x0082 : 0 ;"CF_DSPBITMAP"
  941. ,0x008E : 0 ;"CF_DSPENHMETAFILE"
  942. ,0x0083 : 0 ;"CF_DSPMETAFILEPICT"
  943. ,0x0081 : 0 ;"CF_DSPTEXT"
  944. ,0x0080 : 0 ;"CF_OWNERDISPLAY"
  945. ,3 : 0 ;"CF_METAFILEPICT"
  946. ,7 : 0 ;"CF_OEMTEXT"
  947. ,1 : 0 } ;"CF_TEXT"
  948. static formatByValue := { 2 : "CF_BITMAP"
  949. ,8 : "CF_DIB"
  950. ,17 : "CF_DIBV5"
  951. ,5 : "CF_DIF"
  952. ,0x0082 : "CF_DSPBITMAP"
  953. ,0x008E : "CF_DSPENHMETAFILE"
  954. ,0x0083 : "CF_DSPMETAFILEPICT"
  955. ,0x0081 : "CF_DSPTEXT"
  956. ,14 : "CF_ENHMETAFILE"
  957. ,0x0300 : "CF_GDIOBJFIRST"
  958. ,0x03FF : "CF_GDIOBJLAST"
  959. ,15 : "CF_HDROP"
  960. ,16 : "CF_LOCALE"
  961. ,3 : "CF_METAFILEPICT"
  962. ,7 : "CF_OEMTEXT"
  963. ,0x0080 : "CF_OWNERDISPLAY"
  964. ,9 : "CF_PALETTE"
  965. ,10 : "CF_PENDATA"
  966. ,0x0200 : "CF_PRIVATEFIRST"
  967. ,0x02FF : "CF_PRIVATELAST"
  968. ,11 : "CF_RIFF"
  969. ,4 : "CF_SYLK"
  970. ,1 : "CF_TEXT"
  971. ,6 : "CF_TIFF"
  972. ,13 : "CF_UNICODETEXT"
  973. ,12 : "CF_WAVE" }
  974. }