簡體   English   中英

如何使用文件映射發送位圖和文本數據思維過程?

[英]How to send a bitmap and text data thought processes using file mapping?

我嘗試使用file mappingbitmap和一些text字符串從腳本發送到另一個腳本,以下是我的嘗試:

FM := new FileMapping()
Return

F1:: FM.Read()
Esc::ExitApp

F2:: ; Write the pbitmap to map

; GDIp startup
VarSetCapacity(si, 8 + A_PtrSize*2, 0), si := Chr(1)
DllCall("gdiplus\GdiplusStartup", "UPtrP", pToken, "Ptr", &si, "Ptr", 0)
; ------------------------------------------------------------------------

; Create the pBitmap #1
File := "test.png"
DllCall("gdiplus\GdipCreateBitmapFromFile", "WStr", File, "PtrP", pBitmap)
; ------------------------------------------------------------------------

; LockBits #2
DllCall("gdiplus\GdipGetImageDimension", Ptr, pBitmap, "float*", width, "float*", height)
DllCall("gdiplus\GdipGetImagePixelFormat", "Ptr", pBitmap, "PtrP", pixelFormat)

VarSetCapacity(Rect, 16)
NumPut(0, Rect, 0, "UInt")
NumPut(0, Rect, 4, "UInt")
NumPut(width, Rect, 8, "UInt")
NumPut(height, Rect, 12, "UInt")

VarSetCapacity(BitmapData, 16+2*(A_PtrSize ? A_PtrSize : 4), 0)
E := DllCall("Gdiplus\GdipBitmapLockBits", "Ptr", pBitmap, "Ptr", &Rect, "UInt", LockMode:=3, "Int", PixelFormat, "Ptr", &BitmapData)
Stride := NumGet(BitmapData, 8, "Int")
Scan0  := NumGet(BitmapData, 16)
size := stride * height
; ------------------------------------------------------------------------


; Append a string into the data 
; that will be saved on memory #3
str  := "test test"
      
VarSetCapacity(data, dataSize := size + 16 + StrLen(str)*2 + 2, 0)
StrPut(str, &data + size + 16)

; Copty the data to memory #4
DllCall("RtlCopyMemory", "Ptr", &data + 16, "Ptr", scan0, "Ptr", size)

DllCall("Gdiplus\GdipBitmapUnlockBits", "UPtr", pBitmap, "UPtr", &BitmapData) 

; ------------------------------------------------------------------------


; Write to map #5
NumPut(pixelFormat, data)
NumPut(width      , data, 4)
NumPut(height     , data, 8)
NumPut(stride     , data, 12, "UInt")

VarSetCapacity(COPYDATASTRUCT, A_PtrSize*3, 0)
NumPut(dataSize, COPYDATASTRUCT, A_PtrSize)
NumPut(&data, COPYDATASTRUCT, A_PtrSize*2)

FM.Write(&COPYDATASTRUCT)
; ------------------------------------------------------------------------

Return



Class FileMapping {
   
   __New(Name="Global\MyFileMappingObject", BufSize=100000) {    
      
      ; Opens existing or creates new file mapping object
      static INVALID_HANDLE_VALUE := -1, PAGE_READWRITE := 0x4, FILE_MAP_ALL_ACCESS := 0xF001F
      
      hMapFile := DllCall("OpenFileMapping", "Ptr", FILE_MAP_ALL_ACCESS, "Int", 0, "Str", Name)
      
      if ( hMapFile == 0 ) {        
         ; OpenFileMapping Failed - file mapping object doesn't exist - that means we have to create it
         hMapFile := DllCall("CreateFileMapping", "Ptr", INVALID_HANDLE_VALUE, "Ptr", 0, "Int", PAGE_READWRITE, "Int", 0, "Int", BufSize, "Str", Name)
         if ( hMapFile == 0 )    ; CreateFileMapping Failed
               return
      }

      pBuf := DllCall("MapViewOfFile", "Ptr", hMapFile, "Int", FILE_MAP_ALL_ACCESS, "Int", 0, "Int", 0, "Ptr", BufSize)
      
      if ( pBuf == 0 ) ; MapViewOfFile Failed
         return

      this.Name     := Name
      this.hMapFile := hMapFile
      this.pBuf     := pBuf
      this.BufSize  := BufSize
      
   }
   


   Write(data:="") {       
      NumPut(data, this.pBuf)
   }



   Read() {

      static flags := HEAP_ZERO_MEMORY := 0x00000008
         , hHeap := DllCall("GetProcessHeap", "Ptr")

      param := NumGet(this.pBuf)
      size  := NumGet(param + A_PtrSize, "UInt")
      pData := NumGet(param + A_PtrSize*2)

      pHeap := DllCall("HeapAlloc", "Ptr", hHeap, "UInt", flags, "UPtr", size, "Ptr")
      DllCall("RtlCopyMemory", "Ptr", pHeap, "Ptr", pData, "Ptr", size)

      this.CreateBitmapFromData(hHeap, pHeap)
      return

   }



   CreateBitmapFromData(hHeap, pImageData) {

      pixelFormat := NumGet(pImageData+0, "UInt")
      width       := NumGet(pImageData+4, "UInt")
      height      := NumGet(pImageData+8, "UInt")
      stride      := NumGet(pImageData+12,"UInt")
      ; The string appended in the step #3 ("test test")
      str         := StrGet(pImageData + 16 + stride*height)


      
      DllCall("gdiplus\GdipCreateBitmapFromScan0", "Int", width, "Int", height, "Int", stride, "Int", pixelFormat, "Ptr", pImageData + 16, "PtrP", pBitmap)

      DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "PtrP", hbm, "Int", 0xffffffff)

      ; Just for test, create a gui showing the picture.
      Gui, Add, Picture, x0 y0, % "HBITMAP:" hbm
      Gui, Show

      DllCall("HeapFree", "Ptr", hHeap, "UInt", 0, "Ptr", pImageData)
      DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap)

   }



   __Delete() {
      DllCall("UnmapViewOfFile", "Ptr", this.pBuf), DllCall("CloseHandle", "Ptr", this.hMapFile)
   }

}

要將位圖和文本寫入文件映射,請F2

它將從給定文件創建一個位圖(#1)

在位圖上調用 lockbits(#2),將掃描和字符串 (#3) 保存到data中並利用RtlCopyMemorydata復制到內存 (#4)

然后,將data保存到文件映射中(#5)

當您按F1時,它將從Class FileMap調用函數Read()並“重建”已保存在文件映射內的位圖 ( CreateBitmapFromData ),並讀取步驟 #3 中附加的字符串

只要從同一個腳本讀取/寫入,事情就可以正常工作,如果我啟動不同的進程並調用FM.Read()它不起作用,則函數Read()內的sizepData的值是空白的:

  param := NumGet(this.pBuf)
  size  := NumGet(param + A_PtrSize, "UInt")
  pData := NumGet(param + A_PtrSize*2)

感謝您對此的任何幫助!

您必須添加更多錯誤處理。 檢查所有返回值並調用

DllCall("GetLastError") 

在不返回錯誤代碼的函數之后。 這將說明正在發生的事情。 沒有這個,就很難給出一個完整的答案,因為有很多事情可能會出錯。

使用 VS Code 的 AutoHotkey 調試器擴展之一,如下所示: AutoHotkey Plus

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM