Jump to content

Working with ScreenCapture & HBITMAP


Recommended Posts

I'm trying to write an ImageSearch routine similar to the one in AutoHotkey, and I'm stuck with a (probably) very amateuri-ish problem.

_ScreenCapture_Capture("") is returning a HBITMAP handle. What do I do with that? I just want the raw bitmap data (the same I would get by using a binary FileOpen/FileRead on a bitmap file). I don't want to let ScreenCapture create the file, then read it from there, because that would lead to a lot of disk access.

Thanks in advance.

Link to comment
Share on other sites

What do you want to do with it?

Set to Image Control? Look at _SetBitmapToCtrl from resources.au3

Or use other functions from GDIPlus :)

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

There is a Function called _GDIPlus_BitmapCreateFromHBITMAP, which is supposed to take a HBITMAP and return a "bitmap object". But I don't see anything that can be used to access the bitmap data.

It's probably so obvious that noone can be bothered to post it...

Link to comment
Share on other sites

Even though MS defines GetBitmapBits/SetBitmapBits to be obsolete, you can still use them:

#include <WinAPI.au3>
#Include <ScreenCapture.au3>

$hBmp = _ScreenCapture_Capture("", 0, 0, 16, 16)
$aSize = DllCall('gdi32.dll', 'int', 'GetBitmapBits', 'ptr', $hBmp, 'int', 0, 'ptr', 0)
If $aSize[0] Then
    $tBits = DllStructCreate('byte[' & $aSize[0] & ']')
    DllCall('gdi32.dll', 'int', 'GetBitmapBits', 'ptr', $hBmp, 'int', $aSize[0], 'ptr', DllStructGetPtr($tBits))
    $sHex = Hex(DllStructGetData($tBits, 1))
    MsgBox(0, '', $sHex)
EndIf
_WinAPI_DeleteObject($hBmp)

Exit

"be smart, drink your wine"

Link to comment
Share on other sites

That would be GetDIBits, but for that you also need the handle to DC in which the bitmap is selected, so you'd have to do what _ScreenCapture_Capture() does and call GetDIBits after BitBlt.

"be smart, drink your wine"

Link to comment
Share on other sites

Hmmm, what about this:

$hbmp = _ScreenCapture_Capture("")
$himg = _GDIPlus_BitmapCreateFromHBITMAP($hbmp)
$gfx = _GDIPlus_ImageGetGraphicsContext($himg)
$dc = _GDIPlus_GraphicsGetDC($gfx)

And then use GetDIBits?

Link to comment
Share on other sites

Your solution works fine, BTW, thanks a lot, Siao. A problem is, that I get a 32bit BMP, though, no matter what I set with _ScreenCapture_SetBMPFormat().

Anyone see a quick operation to dump the additional byte? Or a way to get a 24bit BMP that needs no post-processing?

Edited by zagibu
Link to comment
Share on other sites

#include <WinAPI.au3>

Const $DIB_RGB_COLORS = 0
$iWidth = 16;@DesktopWidth
$iHeight = 16;@DesktopHeight
$iBitCount = 24
$tBMI = DllStructCreate($tagBITMAPINFO)
        DllStructSetData($tBMI, "Size", DllStructGetSize($tBMI) - 4)
        DllStructSetData($tBMI, "Width", $iWidth)
        DllStructSetData($tBMI, "Height", -$iHeight)
        DllStructSetData($tBMI, "Planes", 1)
        DllStructSetData($tBMI, "BitCount", $iBitCount)
$hDC = _WinAPI_GetDC(0)
$hCDC = _WinAPI_CreateCompatibleDC($hDC)
$aDIB = DllCall('gdi32.dll','ptr','CreateDIBSection', 'ptr',0, 'ptr',DllStructGetPtr($tBMI), 'uint',$DIB_RGB_COLORS, 'ptr*',0, 'ptr',0, 'uint',0)
_WinAPI_DeleteObject(_WinAPI_SelectObject($hCDC, $aDIB[0]))
_WinAPI_BitBlt($hCDC, 0, 0, $iWidth, $iHeight, $hDC, 0, 0, $SRCCOPY)
$tBits = DllStructCreate('byte[' & $iWidth*$iHeight*$iBitCount/8 & ']', $aDIB[4])
        $sHex = Hex(DllStructGetData($tBits, 1))
        MsgBox(0, '', $sHex)

_WinAPI_DeleteObject($aDIB[0])
_WinAPI_DeleteDC($hCDC)
_WinAPI_ReleaseDC(0, $hDC)

"be smart, drink your wine"

Link to comment
Share on other sites

  • 1 month later...

I had been trying to use GetDIBits, without success.

Thank-you very much, Siao. This entire script is very helpful.

what if i want to read a .bmp file with the same format? this seems to read a region in a desktop so i want to compare the 2.

Thanks.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...