Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

loading a bitmap image from file into a device context


  • Please log in to reply
2 replies to this topic
glucos
  • Members
  • 4 posts
  • Last active: Nov 19 2011 09:01 PM
  • Joined: 14 Nov 2011
I am pretty new to programming but I have written a few working scripts. Recently, I got the idea to write a script that would compare a cursor to a stored image, and after looking for a while I found ScreenCapture by Sean:

http://www.autohotke...t=screencapture

I was able to adjust Sean's script so that it just saves the cursor in the clipboard as a bitmap image. Although you don't really need to read this part, it might help you understand my problem.
;This script's purpose is to make a bitmap image of the active cursor and save it to the clippboard

^z::
	VarSetCapacity(mi, 20, 0), mi := Chr(20)
	DllCall("GetCursorInfo", "Uint", &mi)
	bShow   := NumGet(mi, 4)		;1 ==> cursor is visible (MSDN)
	hCursor := NumGet(mi, 8)		;cursor handle
	xCursor := NumGet(mi,12)		;not really needed for this script, but might want later
	yCursor := NumGet(mi,16)		;same as ^

	If	bShow && hCursor:=DllCall("CopyIcon", "Uint", hCursor)
	{
	VarSetCapacity(ni, 20, 0)
	DllCall("GetIconInfo", "Uint", hCursor, "Uint", &ni)
	bIcon    := NumGet(ni, 0)		;is cursor ==> false, is icon ==> true
	xHotspot := NumGet(ni, 4)		;I think this is the click location
	yHotspot := NumGet(ni, 8)
	hBMMask  := NumGet(ni,12)		;again not used in script
	hBMColor := NumGet(ni,16)		;same as ^

;the tiny part I added starts here
	mDC := DllCall("CreateCompatibleDC", "Uint", 0)		;make a DC compatible with screen
	hBM := CreateDIBSection(mDC, 32, 32)			;I think this makes a blank bitmap based on mDC (except dimensions)
	oBM := DllCall("SelectObject", "Uint", mDC, "Uint", hBM)	;put hBM into the DC but save original DC in oBM
;ends here

	DllCall("DrawIcon", "Uint", mDC, "int", 0, "int", 0, "Uint", hCursor)	;draw the icon into the DC
	DllCall("DestroyIcon", "Uint", hCursor)				;clear the memory of uneeded objects
	If	hBMMask
	DllCall("DeleteObject", "Uint", hBMMask)
	If	hBMColor
	DllCall("DeleteObject", "Uint", hBMColor)
	}

	DllCall("SelectObject", "Uint", mDC, "Uint", oBM)		;switch back to original DC then delete
	DllCall("DeleteDC", "Uint", mDC)
	SetClipboardData(hBM)				;put the image on the clipboard
return

CreateDIBSection(hDC, nW, nH, bpp = 32, ByRef pBits = "")
{
	NumPut(VarSetCapacity(bi, 40, 0), bi)
	NumPut(nW, bi, 4)
	NumPut(nH, bi, 8)
	NumPut(bpp, NumPut(1, bi, 12, "UShort"), 0, "Ushort")
	NumPut(0,  bi,16)
	Return	DllCall("gdi32\CreateDIBSection", "Uint", hDC, "Uint", &bi, "Uint", 0, "UintP", pBits, "Uint", 0, "Uint", 0)
}

SetClipboardData(hBitmap)
{
	DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
	hDIB :=	DllCall("GlobalAlloc", "Uint", 2, "Uint", 40+NumGet(oi,44))
	pDIB :=	DllCall("GlobalLock", "Uint", hDIB)
	DllCall("RtlMoveMemory", "Uint", pDIB, "Uint", &oi+24, "Uint", 40)
	DllCall("RtlMoveMemory", "Uint", pDIB+40, "Uint", NumGet(oi,20), "Uint", NumGet(oi,44))
	DllCall("GlobalUnlock", "Uint", hDIB)
	DllCall("DeleteObject", "Uint", hBitmap)
	DllCall("OpenClipboard", "Uint", 0)
	DllCall("EmptyClipboard")
	DllCall("SetClipboardData", "Uint", 8, "Uint", hDIB)
	DllCall("CloseClipboard")
}

My problem is in the next code section, and I'm pretty sure it has something to do with how I treat the DC's. This is the script that I want to compare two bitmaps loaded into device contexts. I decided to use the GetPixel() function, I am planning to refine this code, but not until it's working. I believe I have traced the problem to the bitmap not succsesfully loading into the DC. The returned handle for hBM1 is negative, and according to MSDN the return value will be NULL if it didn't work. Is a negative handle NULL?

;this script is supposed to take two .bmp files and compare them pixel for pixel when you press CTRL + C
;(doesn't work yet)

#p::Pause

^c::
hBM1 := LoadBMPIntoDC ("file_address")	;put in address of a 32X32 bitmap
hBM2 := LoadBMPIntoDC ("file_address")	;put in address of a 32X32 bitmap
result := CompareBMP32(hBM1, hBM2)
if result = 1
MsgBox, "didn't match"
else
MsgBox, "matched"
return


CreateDIBSection(hDC, nW, nH, bpp = 32, ByRef pBits = "")
{
	NumPut(VarSetCapacity(bi, 40, 0), bi)
	NumPut(nW, bi, 4)
	NumPut(nH, bi, 8)
	NumPut(bpp, NumPut(1, bi, 12, "UShort"), 0, "Ushort")
	NumPut(0,  bi,16)
	Return	DllCall("gdi32\CreateDIBSection", "Uint", hDC, "Uint", &bi, "Uint", 0, "UintP", pBits, "Uint", 0, "Uint", 0)
}

;this function is the broken one, I cant seem to get the .bmp from file into DC
LoadBMPIntoDC(bmpfile)
{
	hBmp := DllCall("LoadImage","Uint", 0, "str", bmpfile, "Uint", 0, "int", 32, "int",32, "Uint", 0x00000010)	;load the image [color=red](check my syntax here)[/color]
	mDC := DllCall("CreateCompatibleDC", "Uint", 0)						;create screen compatible DC
	hBM := CreateDIBSection(mDC, 32, 32)	;I suspect that this part is not really needed (makes blank bmp based on mDC)
	oBM := DllCall("SelectObject", "Uint", mDC, "Uint", hBM)	;puts hBM in mDC
	DllCall("BitBlt", "Uint", mDC, "int", 0, "int", 0, "int", 32, "int", 32, "Uint", hBmp, "int", 0, "int", 0, "Uint", 0x40000000 | 

0x00CC0020)	;blits hBmp over mDC
	DllCall("SelectObject", "Uint", mDC, "Uint", oBM)	;puts original DC back in mDC then deletes
	DllCall("DeleteDC", "Uint", mDC)
	return hBM
}

;comparison function
CompareBMP32(hBM1, hBM2)
{
	mDC1 := DllCall("CreateCompatibleDC", "Uint", 0)
	mDC2 := DllCall("CreateCompatibleDC", "Uint", 0)
	oBM1 := DllCall("SelectObject", "Uint", mDC1, "Uint", hBM1)
	oBM2 := DllCall("SelectObject", "Uint", mDC2, "Uint", hBM2)
	DllCall("SelectObject", "Uint", mDC1, "Uint", oBM1)
	DllCall("SelectObject", "Uint", mDC2, "Uint", oBM2)
	while x < 32
	{
		while y < 32
		{
			color1 := DllCall("GetPixel", "Uint", mDC1, "int", x, "int", y)
			color2 := DllCall("GetPixel", "Uint", mDC2, "int", x, "int", y)
			if color1<>color2
			return 1
			y+=1
		}
		x+=1
	}
	DllCall("DeleteDC", "Uint", mDC1)
	DllCall("DeleteDC", "Uint", mDC2)
	DllCall("DeleteObject", "Uint", hBM1)
	DllCall("DeleteObject", "Uint", hBM2)
	return 0
}

I really don't know much about DC's. I have been reading about them on MSDN, but I still dont fully understand them. I would appreciate any help.

SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005
I notice one problem:

;(doesn't work yet)

#p::Pause

^c::
hBM1 := LoadBMPIntoDC ("file_address")   ;put in address of a 32X32 bitmap
hBM2 := LoadBMPIntoDC ("file_address")   ;put in address of a 32X32 bitmap


There should be no space between a function name and the opening bracket.
For example:

LoadBMPIntoDC ("file_address")
should be
LoadBMPIntoDC("file_address")
kWo4Lk1.png

glucos
  • Members
  • 4 posts
  • Last active: Nov 19 2011 09:01 PM
  • Joined: 14 Nov 2011
Thanks, that was one of the problems, but the main one turned out to be not doing GetObject on the handles. Explains why I only seemed to get numbers. :?