【GIF到剪贴板示例】WinClip

 #NoEnv
SetBatchLines, -1

; #################################
;        参数处理
; #################################

;拖动图片文件到脚本上,自动存到剪贴板中
ImageFile = %1%

; 展开为完整路径
if !RegExMatch(ImageFile, "i)^(https?|ftp)://")
{
Loop, %ImageFile%
ImageFile := A_LoopFileLongPath
}

; #################################
;        复制到剪贴板
; #################################

html =
(
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD></HEAD>
<BODY><!--StartFragment--><IMG src="%ImageFile%"><!--EndFragment--></BODY>
</HTML>
)

WinClip.Clear()
WinClip.SetHTML( html )

if RegExMatch(ImageFile, "i)^(https?|ftp)://")
return

WinClip.SetFiles( ImageFile )
WinClip.SetBitmap( ImageFile )
return
 ;=========================================
class WinClip extends WinClip_base
{
  _toclipboard( ByRef data, size ) ;==================================
  {
    if !WinClipAPI.OpenClipboard()
      return 0
    offset := 0
    lastPartOffset := 0
    WinClipAPI.EmptyClipboard()
    while ( offset < size )
    {
      if !( fmt := NumGet( data, offset, "UInt" ) )
        break
      offset += 4
      if !( dataSize := NumGet( data, offset, "UInt" ) )
        break
      offset += 4
      if ( ( offset + dataSize ) > size )
        break
      if !( pData := WinClipAPI.GlobalLock( WinClipAPI.GlobalAlloc( 0x0042, dataSize ) ) )
      {
        offset += dataSize
        continue
      }
      WinClipAPI.memcopy( pData, &data + offset, dataSize )
      if ( fmt == this.ClipboardFormats.CF_ENHMETAFILE )
        pClipData := WinClipAPI.SetEnhMetaFileBits( pData, dataSize )
      else
        pClipData := pData
      if !pClipData
        continue
      WinClipAPI.SetClipboardData( fmt, pClipData )
      if ( fmt == this.ClipboardFormats.CF_ENHMETAFILE )
        WinClipAPI.DeleteEnhMetaFile( pClipData )
      WinClipAPI.GlobalUnlock( pData )
      offset += dataSize
      lastPartOffset := offset
    }
    WinClipAPI.CloseClipboard()
    return lastPartOffset
  }
  
   _compileClipData( ByRef out_data, objClip ) ;==================================
  {
    if !IsObject( objClip )
      return 0
    ;calculating required data size
    clipSize := 0
    for fmt, params in objClip
      clipSize += 8 + params.size
    VarSetCapacity( out_data, clipSize, 0 )
    offset := 0
    for fmt, params in objClip
    {
      NumPut( fmt, out_data, offset, "UInt" )
      offset += 4
      NumPut( params.size, out_data, offset, "UInt" )
      offset += 4
      WinClipAPI.memcopy( &out_data + offset, ObjGetAddress( params, "buffer" ), params.size )
      offset += params.size
    }
    return clipSize
  }
  
  _fromclipboard( ByRef clipData ) ;==================================
  {
    if !WinClipAPI.OpenClipboard()
      return 0
    nextformat := 0
    objFormats := object()
    clipSize := 0
    formatsNum := 0
    while ( nextformat := WinClipAPI.EnumClipboardFormats( nextformat ) )
    {
      if this.skipFormats.hasKey( nextformat )
        continue
      if ( dataHandle := WinClipAPI.GetClipboardData( nextformat ) )
      {
        pObjPtr := 0, nObjSize := 0
        if ( nextFormat == this.ClipboardFormats.CF_ENHMETAFILE )
        {
          if ( bufSize := WinClipAPI.GetEnhMetaFileBits( dataHandle, hemfBuf ) )
            pObjPtr := &hemfBuf, nObjSize := bufSize
        }
        else if ( nSize := WinClipAPI.GlobalSize( WinClipAPI.GlobalLock( dataHandle ) ) )
          pObjPtr := dataHandle, nObjSize := nSize
        else
          continue
        if !( pObjPtr && nObjSize )
          continue
        objFormats[ nextformat ] := { handle : pObjPtr, size : nObjSize }
        clipSize += nObjSize
        formatsNum++
      }
    }
    structSize := formatsNum*( 4 + 4 ) + clipSize  ;allocating 4 bytes for format ID and 4 for data size
    if !structSize
      return 0
    VarSetCapacity( clipData, structSize, 0 )
    ; array in form of:
    ; format   UInt
    ; dataSize UInt
    ; data     Byte[]
    offset := 0
    for fmt, params in objFormats
    {
      NumPut( fmt, &clipData, offset, "UInt" )
      offset += 4
      NumPut( params.size, &clipData, offset, "UInt" )
      offset += 4
      WinClipAPI.memcopy( &clipData + offset, params.handle, params.size )
      offset += params.size
      WinClipAPI.GlobalUnlock( params.handle )
    }
    WinClipAPI.CloseClipboard()
    return structSize
  }
  
  _IsInstance( funcName ) ;==================================
  {
    if !this.isinstance
    {
      throw Exception( "Error in '" funcName "':`nInstantiate the object first to use this method!", -1 )
      return 0
    }
    return 1
  }
 
  _getClipData( ByRef data ) ;==================================
  {
    if !( clipSize := ObjGetCapacity( this, "allData" ) )
      return 0
    if !( pData := ObjGetAddress( this, "allData" ) )
      return 0
    VarSetCapacity( data, clipSize, 0 )
    WinClipAPI.memcopy( &data, pData, clipSize )
    return clipSize
  }
  
  _parseClipboardData( ByRef data, size ) ;==================================
  {
    offset := 0
    formats := object()
    while ( offset < size )
    {
      if !( fmt := NumGet( data, offset, "UInt" ) )
        break
      offset += 4
      if !( dataSize := NumGet( data, offset, "UInt" ) )
        break
      offset += 4
      if ( ( offset + dataSize ) > size )
        break
      params := { name : this._getFormatName( fmt ), size : dataSize }
      ObjSetCapacity( params, "buffer", dataSize )
      pBuf := ObjGetAddress( params, "buffer" )
      WinClipAPI.memcopy( pBuf, &data + offset, dataSize )
      formats[ fmt ] := params
      offset += dataSize
    }
    return formats
  }
  
  Clear() ;==================================
  {
    if !WinClipAPI.OpenClipboard()
      return 0
    WinClipAPI.EmptyClipboard()
    WinClipAPI.CloseClipboard()
    return 1
  }
  
  SetHTML( html, source = "" ) ;==================================
  {
    if ( html = "" )
      return 0
    clipSize :=  this._fromclipboard( clipData )
    if !( clipSize := this._setHTML( clipData, clipSize, html, source ) )
      return 0
    return this._toclipboard( clipData, clipSize )
  }

  iSetHTML( html, source = "" ) ;==================================
  {
    if ( html = "" )
      return 0
    this._IsInstance( A_ThisFunc )
    clipSize := this._getClipData( clipData )
    if !( clipSize := this._setHTML( clipData, clipSize, html, source ) )
      return 0
    return this._setClipData( clipData, clipSize )
  }

  _calcHTMLLen( num ) ;==================================
  {
    while ( StrLen( num ) < 10 )
      num := "0" . num
    return num
  }


  _setHTML( ByRef clipData, clipSize, htmlData, source ) ;==================================
  {
    objFormats := this._parseClipboardData( clipData, clipSize )
    uFmt := WinClipAPI.RegisterClipboardFormat( "HTML Format" )
    objFormats[ uFmt ] := object()
    encoding := "UTF-8"
    htmlLen := StrPut( htmlData, encoding ) - 1   ;substract null
    srcLen := 2 + 10 + StrPut( source, encoding ) - 1      ;substract null
    StartHTML := this._calcHTMLLen( 105 + srcLen )
    EndHTML := this._calcHTMLLen( StartHTML + htmlLen + 76 )
    StartFragment := this._calcHTMLLen( StartHTML + 38 )
    EndFragment := this._calcHTMLLen( StartFragment + htmlLen )
    html =
    ( Join`r`n
Version:0.9
StartHTML:%StartHTML%
EndHTML:%EndHTML%
StartFragment:%StartFragment%
EndFragment:%EndFragment%
SourceURL:%source%
<html>
<body>
<!--StartFragment-->
%htmlData%
<!--EndFragment-->
</body>
</html>
    )
    sLen := StrPut( html, encoding )
    ObjSetCapacity( objFormats[ uFmt ], "buffer", sLen )
    StrPut( html, ObjGetAddress( objFormats[ uFmt ], "buffer" ), sLen, encoding )
    objFormats[ uFmt ].size := sLen
    return this._compileClipData( clipData, objFormats )
  }
  
  _getFiles( pDROPFILES ) ;==================================
  {
    fWide := numget( pDROPFILES + 0, 16, "uchar" ) ;getting fWide value from DROPFILES struct
    pFiles := numget( pDROPFILES + 0, 0, "UInt" ) + pDROPFILES  ;getting address of files list
    list := ""
    while numget( pFiles + 0, 0, fWide ? "UShort" : "UChar" )
    {
      lastPath := strget( pFiles+0, fWide ? "UTF-16" : "CP0" )
      list .= ( list ? "`n" : "" ) lastPath
      pFiles += ( StrLen( lastPath ) + 1 ) * ( fWide ? 2 : 1 )
    }
    return list
  }
  
  _setFiles( ByRef clipData, clipSize, files, append = 0, isCut = 0 ) ;==================================
  {
    objFormats := this._parseClipboardData( clipData, clipSize )
    uFmt := this.ClipboardFormats.CF_HDROP
    if ( append && objFormats.haskey( uFmt ) )
      prevList := this._getFiles( ObjGetAddress( objFormats[ uFmt ], "buffer" ) ) "`n"
    objFiles := WinClipAPI.StrSplit( prevList . files, "`n", A_Space A_Tab )
    objFiles := WinClipAPI.RemoveDubls( objFiles )
    if !objFiles.MaxIndex()
      return 0
    objFormats[ uFmt ] := object()
    DROP_size := 20 + 2
    for i,str in objFiles
      DROP_size += ( StrLen( str ) + 1 ) * 2
    VarSetCapacity( DROPFILES, DROP_size, 0 )
    NumPut( 20, DROPFILES, 0, "UInt" )  ;offset
    NumPut( 1, DROPFILES, 16, "uchar" ) ;NumPut( 20, DROPFILES, 0, "UInt" )
    offset := &DROPFILES + 20
    for i,str in objFiles
    {
      StrPut( str, offset, "UTF-16" )
      offset += ( StrLen( str ) + 1 ) * 2
    }
    ObjSetCapacity( objFormats[ uFmt ], "buffer", DROP_size )
    WinClipAPI.memcopy( ObjGetAddress( objFormats[ uFmt ], "buffer" ), &DROPFILES, DROP_size )
    objFormats[ uFmt ].size := DROP_size
    prefFmt := WinClipAPI.RegisterClipboardFormat( "Preferred DropEffect" )
    objFormats[ prefFmt ] := { size : 4 }
    ObjSetCapacity( objFormats[ prefFmt ], "buffer", 4 )
    NumPut( isCut ? 2 : 5, ObjGetAddress( objFormats[ prefFmt ], "buffer" ), 0 "UInt" )
    return this._compileClipData( clipData, objFormats )
  }
  
  SetFiles( files, isCut = 0 ) ;==================================
  {
    if ( files = "" )
      return 0
    clipSize := this._fromclipboard( clipData )
    if !( clipSize := this._setFiles( clipData, clipSize, files, 0, isCut ) )
      return 0
    return this._toclipboard( clipData, clipSize )
  }

  _BITMAPtoDIB( bitmap, ByRef DIB ) ;==================================
  {
    if !bitmap
      return 0
    if !WinClipAPI.IsInteger( bitmap )
    {
      gdip_token := WinClipAPI.Gdip_Startup()
      DllCall("gdiplus\GdipCreateBitmapFromFileICM", "wstr", bitmap, "Ptr*", pBitmap )
      DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "Ptr*", hBitmap, "int", 0xffffffff )
      DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap)
      WinClipAPI.Gdip_Shutdown( gdip_token )
      bmMade := 1
    }
    else
      hBitmap := bitmap, bmMade := 0
    if !hBitmap
        return 0
    ;http://www.codeguru.com/Cpp/G-M/bitmap/article.php/c1765
    if !( hdc := DllCall( "GetDC", "Ptr", 0 ) )
      goto, _BITMAPtoDIB_cleanup
    hPal := DllCall( "GetStockObject", "UInt", 15 ) ;DEFAULT_PALLETE
    hPal := DllCall( "SelectPalette", "ptr", hdc, "ptr", hPal, "Uint", 0 )
    DllCall( "RealizePalette", "ptr", hdc )
    size := DllCall( "GetObject", "Ptr", hBitmap, "Uint", 0, "ptr", 0 )
    VarSetCapacity( bm, size, 0 )
    DllCall( "GetObject", "Ptr", hBitmap, "Uint", size, "ptr", &bm )
    biBitCount := NumGet( bm, 16, "UShort" )*NumGet( bm, 18, "UShort" )
    nColors := (1 << biBitCount)
	if ( nColors > 256 ) 
		nColors := 0
	bmiLen  := 40 + nColors * 4
    VarSetCapacity( bmi, bmiLen, 0 )
    ;BITMAPINFOHEADER initialization
    NumPut( 40, bmi, 0, "Uint" )
    NumPut( NumGet( bm, 4, "Uint" ), bmi, 4, "Uint" )   ;width
    NumPut( biHeight := NumGet( bm, 8, "Uint" ), bmi, 8, "Uint" ) ;height
    NumPut( 1, bmi, 12, "UShort" )
    NumPut( biBitCount, bmi, 14, "UShort" )
    NumPut( 0, bmi, 16, "UInt" ) ;compression must be BI_RGB

    ; Get BITMAPINFO. 
    if !DllCall("GetDIBits"
              ,"ptr",hdc
              ,"ptr",hBitmap
              ,"uint",0 
              ,"uint",biHeight
              ,"ptr",0      ;lpvBits 
              ,"ptr",&bmi  ;lpbi 
              ,"uint",0)    ;DIB_RGB_COLORS
      goto, _BITMAPtoDIB_cleanup
    biSizeImage := NumGet( &bmi, 20, "UInt" )
    if ( biSizeImage = 0 )
    {
      biBitCount := numget( &bmi, 14, "UShort" )
      biWidth := numget( &bmi, 4, "UInt" )
      biHeight := numget( &bmi, 8, "UInt" )
      biSizeImage := (((( biWidth * biBitCount + 31 ) & ~31 ) >> 3 ) * biHeight )
      ;~ dwCompression := numget( bmi, 16, "UInt" )
      ;~ if ( dwCompression != 0 ) ;BI_RGB
        ;~ biSizeImage := ( biSizeImage * 3 ) / 2
      numput( biSizeImage, &bmi, 20, "UInt" )
    }
    DIBLen := bmiLen + biSizeImage
    VarSetCapacity( DIB, DIBLen, 0 )
    WinClipAPI.memcopy( &DIB, &bmi, bmiLen )
    if !DllCall("GetDIBits"
              ,"ptr",hdc
              ,"ptr",hBitmap
              ,"uint",0 
              ,"uint",biHeight
              ,"ptr",&DIB + bmiLen     ;lpvBits 
              ,"ptr",&DIB  ;lpbi 
              ,"uint",0)    ;DIB_RGB_COLORS
      goto, _BITMAPtoDIB_cleanup
_BITMAPtoDIB_cleanup:
    if bmMade
      DllCall( "DeleteObject", "ptr", hBitmap )
    DllCall( "SelectPalette", "ptr", hdc, "ptr", hPal, "Uint", 0 )
    DllCall( "RealizePalette", "ptr", hdc )
    DllCall("ReleaseDC","ptr",hdc)
    if ( A_ThisLabel = "_BITMAPtoDIB_cleanup" )
      return 0
    return DIBLen
  }
  
  SetBitmap( bitmap ) ;==================================
  {
    if ( DIBSize := this._BITMAPtoDIB( bitmap, DIB ) )
    {
      clipSize := this._fromclipboard( clipData )
      if ( clipSize := this._setBitmap( DIB, DIBSize, clipData, clipSize ) )
        return this._toclipboard( clipData, clipSize )
    }
    return 0
  }

  _setBitmap( ByRef DIB, DIBSize, ByRef clipData, clipSize ) ;==================================
  {
    objFormats := this._parseClipboardData( clipData, clipSize )
    uFmt := this.ClipboardFormats.CF_DIB
    objFormats[ uFmt ] := { size : DIBSize }
    ObjSetCapacity( objFormats[ uFmt ], "buffer", DIBSize )
    WinClipAPI.memcopy( ObjGetAddress( objFormats[ uFmt ], "buffer" ), &DIB, DIBSize )
    return this._compileClipData( clipData, objFormats )
  }

  _getFormatName( iformat ) ;==================================
  {
    if this.formatByValue.HasKey( iformat )
      return this.formatByValue[ iformat ]
    else
      return WinClipAPI.GetClipboardFormatName( iformat )
  }
  
 }

;-------------------------------------------------------------------
class WinClip_base
{
  __Call( aTarget, aParams* ) {
    if ObjHasKey( WinClip_base, aTarget )
      return WinClip_base[ aTarget ].( this, aParams* )
    throw Exception( "Unknown function '" aTarget "' requested from object '" this.__Class "'", -1 )
  }
  
  Err( msg ) {
    throw Exception( this.__Class " : " msg ( A_LastError != 0 ? "`n" this.ErrorFormat( A_LastError ) : "" ), -2 )
  }
  
  ErrorFormat( error_id ) {
    VarSetCapacity(msg,1000,0)
    if !len := DllCall("FormatMessageW"
          ,"UInt",FORMAT_MESSAGE_FROM_SYSTEM := 0x00001000 | FORMAT_MESSAGE_IGNORE_INSERTS := 0x00000200		;dwflags
          ,"Ptr",0		;lpSource
          ,"UInt",error_id	;dwMessageId
          ,"UInt",0			;dwLanguageId
          ,"Ptr",&msg			;lpBuffer
          ,"UInt",500)			;nSize
      return
    return 	strget(&msg,len)
  }
}

class WinClipAPI_base extends WinClip_base
{
  __Get( name ) {
    if !ObjHasKey( this, initialized )
      this.Init()
    else
      throw Exception( "Unknown field '" name "' requested from object '" this.__Class "'", -1 )
  }
}

class WinClipAPI extends WinClip_base
{
  memcopy( dest, src, size ) { ;==================================
    return DllCall( "msvcrt\memcpy", "ptr", dest, "ptr", src, "uint", size )
  }
  GlobalSize( hObj ) { ;==================================
    return DllCall( "GlobalSize", "Ptr", hObj )
  }
  GlobalLock( hMem ) { ;==================================
    return DllCall( "GlobalLock", "Ptr", hMem )
  }
  GlobalUnlock( hMem ) { ;==================================
    return DllCall( "GlobalUnlock", "Ptr", hMem )
  }
  GlobalAlloc( flags, size ) { ;==================================
    return DllCall( "GlobalAlloc", "Uint", flags, "Uint", size )
  }
  OpenClipboard() { ;==================================
    return DllCall( "OpenClipboard", "Ptr", 0 )
  }
  CloseClipboard() { ;==================================
    return DllCall( "CloseClipboard" )
  }
  SetClipboardData( format, hMem ) { ;==================================
    return DllCall( "SetClipboardData", "Uint", format, "Ptr", hMem )
  }
  GetClipboardData( format ) { ;==================================
    return DllCall( "GetClipboardData", "Uint", format ) 
  }
  EmptyClipboard() { ;==================================
    return DllCall( "EmptyClipboard" )
  }
  EnumClipboardFormats( format ) { ;==================================
    return DllCall( "EnumClipboardFormats", "UInt", format )
  }
  GetClipboardFormatName( iFormat ) { ;==================================
    size := VarSetCapacity( bufName, 255*( A_IsUnicode ? 2 : 1 ), 0 )
    DllCall( "GetClipboardFormatName", "Uint", iFormat, "str", bufName, "Uint", size )
    return bufName
  }
  GetEnhMetaFileBits( hemf, ByRef buf ) { ;==================================
    if !( bufSize := DllCall( "GetEnhMetaFileBits", "Ptr", hemf, "Uint", 0, "Ptr", 0 ) )
      return 0
    VarSetCapacity( buf, bufSize, 0 )
    if !( bytesCopied := DllCall( "GetEnhMetaFileBits", "Ptr", hemf, "Uint", bufSize, "Ptr", &buf ) )
      return 0
    return bytesCopied
  }
  SetEnhMetaFileBits( pBuf, bufSize ) { ;==================================
    return DllCall( "SetEnhMetaFileBits", "Uint", bufSize, "Ptr", pBuf )
  }
  DeleteEnhMetaFile( hemf ) { ;==================================
    return DllCall( "DeleteEnhMetaFile", "Ptr", hemf )
  }

  IsInteger( var ) { ;==================================
    if var is integer
      return True
    else 
      return False
  }

  Gdip_Startup() {
    if !DllCall( "GetModuleHandleW", "Wstr", "gdiplus", "UPtr" )
          DllCall( "LoadLibraryW", "Wstr", "gdiplus", "UPtr" )
    
    VarSetCapacity(GdiplusStartupInput , 3*A_PtrSize, 0), NumPut(1,GdiplusStartupInput ,0,"UInt") ; GdiplusVersion = 1
    DllCall("gdiplus\GdiplusStartup", "Ptr*", pToken, "Ptr", &GdiplusStartupInput, "Ptr", 0)
    return pToken
  }

 Gdip_Shutdown(pToken) {
    DllCall("gdiplus\GdiplusShutdown", "Ptr", pToken)
    if hModule := DllCall( "GetModuleHandleW", "Wstr", "gdiplus", "UPtr" )
      DllCall("FreeLibrary", "Ptr", hModule)
    return 0
  }

  StrSplit(str,delim,omit = "")  ;==================================
  {
    if (strlen(delim) > 1)
    {
      StringReplace,str,str,% delim,ƒ,1 		;■¶╬
      delim = ƒ
    }
    ra := Array()
    loop, parse,str,% delim,% omit
      if (A_LoopField != "")
        ra.Insert(A_LoopField)
    return ra
  }
  RemoveDubls( objArray ) ;==================================
  {
    while True
    {
      nodubls := 1
      tempArr := Object()
      for i,val in objArray
      {
        if tempArr.haskey( val )
        {
          nodubls := 0
          objArray.Remove( i )
          break
        }
        tempArr[ val ] := 1
      }
      if nodubls
        break
    }
    return objArray
  }
  RegisterClipboardFormat( fmtName ) { ;==================================
    return DllCall( "RegisterClipboardFormat", "ptr", &fmtName )
  }

}

给TA捐赠
共{{data.count}}人
人已捐赠
其他

_显示颜色RGB值

2021-12-2 11:50:49

其他

【操作托盘图标】TrayIcon

2021-12-2 11:53:28

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索