如何使用文件映射发送位图和文本数据的思考过程?



我试图发送一个bitmap和一些text字符串从一个脚本到另一个使用file mapping,下面是我的尝试:

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("gdiplusGdiplusStartup", "UPtrP", pToken, "Ptr", &si, "Ptr", 0)
; ------------------------------------------------------------------------
; Create the pBitmap #1
File := "test.png"
DllCall("gdiplusGdipCreateBitmapFromFile", "WStr", File, "PtrP", pBitmap)
; ------------------------------------------------------------------------
; LockBits #2
DllCall("gdiplusGdipGetImageDimension", Ptr, pBitmap, "float*", width, "float*", height)
DllCall("gdiplusGdipGetImagePixelFormat", "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("GdiplusGdipBitmapLockBits", "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("GdiplusGdipBitmapUnlockBits", "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="GlobalMyFileMappingObject", 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("gdiplusGdipCreateBitmapFromScan0", "Int", width, "Int", height, "Int", stride, "Int", pixelFormat, "Ptr", pImageData + 16, "PtrP", pBitmap)
DllCall("gdiplusGdipCreateHBITMAPFromBitmap", "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("gdiplusGdipDisposeImage", "Ptr", pBitmap)
}

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

要将位图和文本写入文件映射,请按F2

它将从给定的文件

创建一个位图(#1)调用位图上的lockbits(#2),将扫描和字符串(#3)保存到data中,并使用RtlCopyMemorydata复制到内存(#4)

然后,将data保存到filemap (#5)

当你点击F1时,它将从Class FileMap调用Read()函数并将'重建'已保存在filemap中的位图(CreateBitmapFromData),并读取步骤#3中附加的字符串

事情工作描述只要它从相同的脚本读/写,如果我启动一个不同的进程并调用FM.Read()它不工作,sizepData的值在函数Read()是空白的:

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

感谢任何帮助!

您必须添加更多的错误处理。检查所有返回值并调用

DllCall("GetLastError") 

函数后不返回错误码的。这将告诉我们发生了什么。如果不这样做,很难给出一个完整的答案,因为有很多事情可能出错。

在VS Code中使用AutoHotkey调试器扩展,如下所示:AutoHotkey +

相关内容

  • 没有找到相关文章

最新更新