效果截图

 

打包下载地址:

 

UDP远程桌面显示_主机端.ahk

/*
使用说明:
先在一台电脑上打开主机端脚本,然后修改【连接端】的第27行参数2的对应IP地址来连接通讯做摄像头视频采集显示。
如果是局域网连接则没有什么限制,填写正确的主机端IP地址即可连接。
如果想互联网连接,至少需要主机端是公网IP+路由端口映射才能互相连接。内网穿透连接没试过

参考资料:https://www.autohotkey.com/boards/viewtopic.php?p=74463#p74463
*/
SetBatchLines -1
SetWorkingDir %A_ScriptDir%
#Include %A_ScriptDir%\Socket.ahk
#include %A_ScriptDir%\Gdip_all.ahk

pToken := Gdip_StartUp()  ; GDI库加载

回复人IP := A_Args[1], 回复人端口 := A_Args[2]

; 首次运行脚本时,回复人IP会为空。此时会建立任意人连接的等待。被连接后会自动更新连接者的IP和端口建立双向通信
if (回复人IP="") {
  ; 建立任意连接的接收对象
  myUdpIn := new SocketUDP()  ; 创建一个新的 udp 对象 "myUdpIn"
  myUdpIn.bind(["addr_any", 65511])  ; "addr_any"为接收所有IP,也可接受指定IP推送
  myUdpIn.onRecv := Func("myRecvCallback")  ; 对传入消息执行回调 "myRecvCallback"。
 } else {
  ; 建立指定IP的收发对象
  myUdp := New BidirectionalUDP()
  ; 参1建立自身接收IP端口,参2为要通信发送的IP端口
  myUdp.Bidirectional(["0.0.0.0", 65511], [回复人IP, 回复人端口])  ; 指定后只能与参2的IP端口进行通信
  myUdp.onRecv := Func("myRecvCallback")  ; 对传入消息执行回调 "myRecvCallback"。
  SetTimer 远程桌面, 20
}
Gui, Add, Picture, vPic, % "HBITMAP:*" hBitmap
Gui, Show, w1000 h620, AHK窗口显示
Return

远程桌面:
pBitmap := Gdip_BitmapFromScreen("0|0|1000|600")  ; 屏幕截图
, outbytes := GdiPlus_SaveImageToBuffer(pBitmap, outBuf, "JPG", 30)
, myUdp.Send(&outBuf, outbytes)
, Gdip_DisposeImage(pBitmap)
Return

myRecvCallback(this) {
  Global
  inbytes := this.Recv(inbuf)  ; 用于接收发送端的二进制,不能大于65536字节=64KB
  if (this.GetRecvIPfrom()!=回复人IP) or (this.GetRecvPort()!=回复人端口)
    RunWait % A_AhkPath " /r """ A_ScriptFullPath """ " this.GetRecvIPfrom() " " this.GetRecvPort()

  DeleteObject(hBitmap)
  , hBitmap := GDIPlus_hBitmapFromBuffer(inbuf, inbytes)
  GuiControl, , Pic, % "HBITMAP:*" hBitmap
  ; ToolTip % "发送者IP:" this.GetRecvIPfrom() ":" this.GetRecvPort() 
}


; 在SocketUDP类的基础上扩展延伸
Class BidirectionalUDP extends SocketUDP {

  Bidirectional(inHostPort, outHostPort) {
    if ((this.socket != -1) || (!(faddr := inNext := this.GetAddrInfo(inHostPort))))
      return 0
    if ((this.socket != -1) || (!(outNext := this.GetAddrInfo(outHostPort))))
      return 0
    While inNext {
      inSockAddrlen := NumGet(inNext + 0, 16, "Uint")
      , inSockAddr := NumGet(inNext + 0, 16 + (2 * A_PtrSize), "Ptr")
      if ((this.socket := DllCall("ws2_32\socket", "int", NumGet(inNext+0, 4, "int"), "int", this.SocketType, "int", this.ProtocolId, "Ptr")) != -1) {
        if (DllCall("ws2_32\bind", "Ptr", this.Socket, "Ptr", inSockAddr, "Uint", inSockAddrlen, "int") = 0) {  ; 建立接收
          outSockAddrlen := NumGet(outNext + 0, 16, "Uint")
          , outSockAddr := NumGet(outNext + 0, 16 + (2 * A_PtrSize), "Ptr")
          if ((r := DllCall("ws2_32\WSAConnect", "Ptr", this.Socket, "Ptr", outSockAddr, "Uint", outSockAddrlen, "Ptr", 0, "Ptr", 0, "Ptr", 0, "Ptr", 0, "int")) = 0) {  ; 建立发送
            DllCall("ws2_32\freeaddrinfo", "Ptr", faddr)
            return this.EventProcRegister(this.FD_READ | this.FD_CLOSE)
          }
        }
        this.Disconnect()
      }
      inNext := NumGet(inNext + 0, 16 + (3 * A_PtrSize), "Ptr")
    }
    throw Exception("Error connecting")
  }

}


GDIPlus_hBitmapFromBuffer(ByRef Buffer, nSize) {  ; by SKAN
  Static hBitmap
  hData := DllCall("GlobalAlloc", "Uint", 2, "Uint", nSize)
  , pData := DllCall("GlobalLock", "Uint", hData)
  , DllCall("RtlMoveMemory", "Uint", pData, "Uint", &Buffer, "Uint", nSize)
  , DllCall("GlobalUnlock", "Uint", hData)
  , DllCall("ole32\CreateStreamOnHGlobal", "Uint", hData, "int", True, "UIntP", pStream)
  , DllCall("gdiplus\GdipCreateBitmapFromStream", "Uint", pStream, "UIntP", pBitmap)
  , DllCall("DeleteObject", "UPtr", hBitmap)
  , DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Uint", pBitmap, "UIntP", hBitmap, "Uint", DllCall("ntdll\RtlUlongByteSwap", "Uint", DllCall("GetSysColor", "int", 15 ) <<8 ) | 0xFF000000)
  , DllCall("GlobalFree", "Ptr", hData)
  , DllCall("gdiplus\GdipDisposeImage", "Uint", pBitmap)
  , DllCall(NumGet( NumGet(1*pStream)+8 ), "Uint", pStream)  ; IStream::Release
  Return hBitmap
}

GdiPlus_SaveImageToBuffer(pBitmap, ByRef Buffer, Type:="JPG", Quality:=75) {
  nCount := nSize := pStream := hData := _p := 0

  If !RegExMatch(Type, "^(?i:BMP|DIB|RLE|JPG|JPEG|JPE|JFIF|GIF|TIF|TIFF|PNG)$")
    Return -1

  Type := "." Type
  , DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", nCount, "uint*", nSize)
  , VarSetCapacity(ci, nSize)
  , DllCall("gdiplus\GdipGetImageEncoders", "uint", nCount, "uint", nSize, "UPtr", &ci)
  If !(nCount && nSize)
    Return -2

  If A_IsUnicode {
    StrGet_Name := "StrGet"
    , N := (A_AhkVersion < 2) ? nCount : "nCount"
    Loop %N% {
      sString := %StrGet_Name%(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
      If !InStr(sString, "*" Type)
        Continue

      pCodec := &ci+idx
      Break
    }
  } Else {
    N := (A_AhkVersion < 2) ? nCount : "nCount"
    Loop %N% {
      Location := NumGet(ci, 76*(A_Index-1)+44)
      , nSize := DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "uint", 0, "int", 0, "uint", 0, "uint", 0)
      , VarSetCapacity(sString, nSize)
      , DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "str", sString, "int", nSize, "uint", 0, "uint", 0)
      If !InStr(sString, "*" Type)
        Continue

      pCodec := &ci+76*(A_Index-1)
      Break
    }
  }

  If !pCodec
    Return -3

  If (Quality!=75) {
    Quality := (Quality < 0) ? 0 : (Quality > 100) ? 100 : Quality
    If (quality>95 && toBase64=1)
      Quality := 95

    If RegExMatch(Type, "^\.(?i:JPG|JPEG|JPE|JFIF)$") {
      DllCall("gdiplus\GdipGetEncoderParameterListSize", "UPtr", pBitmap, "UPtr", pCodec, "uint*", nSize)
      , VarSetCapacity(EncoderParameters, nSize, 0)
      , DllCall("gdiplus\GdipGetEncoderParameterList", "UPtr", pBitmap, "UPtr", pCodec, "uint", nSize, "UPtr", &EncoderParameters)
      , nCount := NumGet(EncoderParameters, "UInt")
      , N := (A_AhkVersion < 2) ? nCount : "nCount"
      Loop %N% {
        elem := (24+A_PtrSize)*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
        If (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6) {
          _p := elem+&EncoderParameters-pad-4
          NumPut(Quality, NumGet(NumPut(4, NumPut(1, _p+0)+20, "UInt")), "UInt")
          Break
        }
      }
    }
  }

  ; Save Image to Stream and copy it to Buffer
  DllCall("ole32\CreateStreamOnHGlobal", "Uint", 0, "int", 1, "UintP", pStream)
  , DllCall("gdiplus\GdipSaveImageToStream", "Uint", pBitmap, "Uint", pStream, "Uint", pCodec, "Uint", _p)
  , DllCall("gdiplus\GdipDisposeImage", "Uint", pBitmap)
  , DllCall("ole32\GetHGlobalFromStream", "Uint", pStream, "UintP", hData)
  , pData := DllCall("GlobalLock", "Uint", hData)
  , nSize := DllCall("GlobalSize", "Uint", pData)
  , VarSetCapacity(Buffer, nSize, 0)
  , DllCall("RtlMoveMemory", "Uint", &Buffer, "Uint", pData, "Uint", nSize)
  , DllCall("GlobalUnlock", "Uint", hData)
  , DllCall(NumGet(NumGet( 1*pStream ) + 8), "Uint", pStream)
  , DllCall("GlobalFree", "Uint", hData)
  Return nSize
}

 

 

UDP远程桌面显示_连接端.ahk

/*
使用说明:
先在一台电脑上打开主机端脚本,然后修改第27行的参数2的对应IP地址来连接通讯做摄像头视频采集显示。
如果是局域网连接则没有什么限制,填写正确的主机端IP地址即可连接。
如果想互联网连接,至少需要主机端是公网IP+路由端口映射才能互相连接。内网穿透连接没试过

参考资料:https://www.autohotkey.com/boards/viewtopic.php?p=74463#p74463
*/
SetBatchLines -1
SetWorkingDir %A_ScriptDir%
#Include %A_ScriptDir%\Socket.ahk
#include %A_ScriptDir%\Gdip_all.ahk

pToken := Gdip_StartUp()  ; GDI库加载

; 建立指定IP的收发对象
myUdp := New BidirectionalUDP()
; 参1建立自身接收IP端口,参2为要通信发送的IP端口【参2一定要设置正确的主机IP和端口】
myUdp.Bidirectional(["0.0.0.0", 65500], ["10.0.0.10", 65511])  ; 指定后只能与参2的IP端口进行通信
myUdp.onRecv := Func("myRecvCallback")  ; 对传入消息执行回调 "myRecvCallback"。
myUdp.SendText("首次连接确认")

SetTimer 远程桌面, 20
Gui, Add, Picture, vPic, % "HBITMAP:*" hBitmap
Gui, Show, w1000 h620, AHK窗口显示
Return

远程桌面:
pBitmap := Gdip_BitmapFromScreen("0|0|1000|600")  ; 屏幕截图
, outbytes := GdiPlus_SaveImageToBuffer(pBitmap, outBuf, "JPG", 30)
, myUdp.Send(&outBuf, outbytes)
, Gdip_DisposeImage(pBitmap)
Return


myRecvCallback(this) {
  Global
  inbytes := this.Recv(inbuf)  ; 用于接收发送端的二进制,不能大于65536字节=64KB
  , DeleteObject(hBitmap)
  , hBitmap := GDIPlus_hBitmapFromBuffer(inbuf, inbytes)
  GuiControl, , Pic, % "HBITMAP:*" hBitmap
  ; ToolTip % "发送者IP:" this.GetRecvIPfrom() ":" this.GetRecvPort() 
}

; 在SocketUDP类的基础上扩展延伸
Class BidirectionalUDP extends SocketUDP {

  Bidirectional(inHostPort, outHostPort) {
    if ((this.socket != -1) || (!(faddr := inNext := this.GetAddrInfo(inHostPort))))
      return 0
    if ((this.socket != -1) || (!(outNext := this.GetAddrInfo(outHostPort))))
      return 0
    While inNext {
      inSockAddrlen := NumGet(inNext + 0, 16, "Uint")
      , inSockAddr := NumGet(inNext + 0, 16 + (2 * A_PtrSize), "Ptr")
      if ((this.socket := DllCall("ws2_32\socket", "int", NumGet(inNext+0, 4, "int"), "int", this.SocketType, "int", this.ProtocolId, "Ptr")) != -1) {
        if (DllCall("ws2_32\bind", "Ptr", this.Socket, "Ptr", inSockAddr, "Uint", inSockAddrlen, "int") = 0) {  ; 建立接收
          outSockAddrlen := NumGet(outNext + 0, 16, "Uint")
          , outSockAddr := NumGet(outNext + 0, 16 + (2 * A_PtrSize), "Ptr")
          if ((r := DllCall("ws2_32\WSAConnect", "Ptr", this.Socket, "Ptr", outSockAddr, "Uint", outSockAddrlen, "Ptr", 0, "Ptr", 0, "Ptr", 0, "Ptr", 0, "int")) = 0) {  ; 建立发送
            DllCall("ws2_32\freeaddrinfo", "Ptr", faddr)
            return this.EventProcRegister(this.FD_READ | this.FD_CLOSE)
          }
        }
        this.Disconnect()
      }
      inNext := NumGet(inNext + 0, 16 + (3 * A_PtrSize), "Ptr")
    }
    throw Exception("Error connecting")
  }

}


GDIPlus_hBitmapFromBuffer(ByRef Buffer, nSize) {  ; by SKAN
  Static hBitmap
  hData := DllCall("GlobalAlloc", "Uint", 2, "Uint", nSize)
  , pData := DllCall("GlobalLock", "Uint", hData)
  , DllCall("RtlMoveMemory", "Uint", pData, "Uint", &Buffer, "Uint", nSize)
  , DllCall("GlobalUnlock", "Uint", hData)
  , DllCall("ole32\CreateStreamOnHGlobal", "Uint", hData, "int", True, "UIntP", pStream)
  , DllCall("gdiplus\GdipCreateBitmapFromStream", "Uint", pStream, "UIntP", pBitmap)
  , DllCall("DeleteObject", "UPtr", hBitmap)
  , DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Uint", pBitmap, "UIntP", hBitmap, "Uint", DllCall("ntdll\RtlUlongByteSwap", "Uint", DllCall("GetSysColor", "int", 15 ) <<8 ) | 0xFF000000)
  , DllCall("GlobalFree", "Ptr", hData)
  , DllCall("gdiplus\GdipDisposeImage", "Uint", pBitmap)
  , DllCall(NumGet( NumGet(1*pStream)+8 ), "Uint", pStream)  ; IStream::Release
  Return hBitmap
}

GdiPlus_SaveImageToBuffer(pBitmap, ByRef Buffer, Type:="JPG", Quality:=75) {
  nCount := nSize := pStream := hData := _p := 0

  If !RegExMatch(Type, "^(?i:BMP|DIB|RLE|JPG|JPEG|JPE|JFIF|GIF|TIF|TIFF|PNG)$")
    Return -1

  Type := "." Type
  , DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", nCount, "uint*", nSize)
  , VarSetCapacity(ci, nSize)
  , DllCall("gdiplus\GdipGetImageEncoders", "uint", nCount, "uint", nSize, "UPtr", &ci)
  If !(nCount && nSize)
    Return -2

  If A_IsUnicode {
    StrGet_Name := "StrGet"
    , N := (A_AhkVersion < 2) ? nCount : "nCount"
    Loop %N% {
      sString := %StrGet_Name%(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
      If !InStr(sString, "*" Type)
        Continue

      pCodec := &ci+idx
      Break
    }
  } Else {
    N := (A_AhkVersion < 2) ? nCount : "nCount"
    Loop %N% {
      Location := NumGet(ci, 76*(A_Index-1)+44)
      , nSize := DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "uint", 0, "int", 0, "uint", 0, "uint", 0)
      , VarSetCapacity(sString, nSize)
      , DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "str", sString, "int", nSize, "uint", 0, "uint", 0)
      If !InStr(sString, "*" Type)
        Continue

      pCodec := &ci+76*(A_Index-1)
      Break
    }
  }

  If !pCodec
    Return -3

  If (Quality!=75) {
    Quality := (Quality < 0) ? 0 : (Quality > 100) ? 100 : Quality
    If (quality>95 && toBase64=1)
      Quality := 95

    If RegExMatch(Type, "^\.(?i:JPG|JPEG|JPE|JFIF)$") {
      DllCall("gdiplus\GdipGetEncoderParameterListSize", "UPtr", pBitmap, "UPtr", pCodec, "uint*", nSize)
      , VarSetCapacity(EncoderParameters, nSize, 0)
      , DllCall("gdiplus\GdipGetEncoderParameterList", "UPtr", pBitmap, "UPtr", pCodec, "uint", nSize, "UPtr", &EncoderParameters)
      , nCount := NumGet(EncoderParameters, "UInt")
      , N := (A_AhkVersion < 2) ? nCount : "nCount"
      Loop %N% {
        elem := (24+A_PtrSize)*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
        If (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6) {
          _p := elem+&EncoderParameters-pad-4
          NumPut(Quality, NumGet(NumPut(4, NumPut(1, _p+0)+20, "UInt")), "UInt")
          Break
        }
      }
    }
  }

  ; Save Image to Stream and copy it to Buffer
  DllCall("ole32\CreateStreamOnHGlobal", "Uint", 0, "int", 1, "UintP", pStream)
  , DllCall("gdiplus\GdipSaveImageToStream", "Uint", pBitmap, "Uint", pStream, "Uint", pCodec, "Uint", _p)
  , DllCall("gdiplus\GdipDisposeImage", "Uint", pBitmap)
  , DllCall("ole32\GetHGlobalFromStream", "Uint", pStream, "UintP", hData)
  , pData := DllCall("GlobalLock", "Uint", hData)
  , nSize := DllCall("GlobalSize", "Uint", pData)
  , VarSetCapacity(Buffer, nSize, 0)
  , DllCall("RtlMoveMemory", "Uint", &Buffer, "Uint", pData, "Uint", nSize)
  , DllCall("GlobalUnlock", "Uint", hData)
  , DllCall(NumGet(NumGet( 1*pStream ) + 8), "Uint", pStream)
  , DllCall("GlobalFree", "Uint", hData)
  Return nSize
}

 

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