DatSik
2012-09-02 11:39:06
Dug this up from when CRUEL used to be around (IS HE GONE FOR GOOD?
———————
1.0 Introduction
———————
GetDIBits is a Windows API that some of you, RS Cheaters, have used to create macroes with.
Typically, the API GetPixel is used, which finds the pixel of a specific HDC on a specific X and Y coordinate. Thus, we could have developed colour searching functions that used GetPixel on all the pixels 1 by 1 in a certain window to find a certain colour.
Some of you have switched to GetDIBits as it is way faster. What this function does is instead of gathering 1 pixel, it takes a "snapshot" of an entire area and gets ALL the pixels. The pixel information are stored inside an ARRAY and you can search for a colour by navigating through the array.
However, GetDIBits is much harder to use (for some people) and that's what this tutorial is about.
Assuming you KNOW the language pretty much and you understand fundamental aspects such as functions and parameters and what an API is…
—————————————
0.0 Section Newb
—————————————
Just to fill in some details… Just in case…
- An API is a function provided by Windows that allows you to interact with it. There are hundreds of these. You declare them in a module or on top of all the code of a form. Usually, you would declare them as Public inside a module so all the parts of your project can use them. You find out the structure of the declaration by opening up your API Viewer.. which you should have.
Example:
You don't memorize API declarations.. That's stupid lol. You just grab the ones you need from the API Viewer and paste them in your module. It simply contains information such as the DLL file the function is in, the name, the parameters etc.
- APIs also include structures and constants… which are declared at the top of everything or inside a module as Public so everything can access them.
- A structure/type in VB6 is a custom variable that contains other primitive variables. Ex:
The POINTAPI type is just a variable that contains two sub-variables: X and Y… which simply represent coordinates. It is part of the API because many API functions rely on POINTAPI to return their results to you.
- A constant is a magic number also in the API that you can get from the API Viewer.. It's in the form or something like this:
Again, you declare them as Public in a module or on top of everything inside a form.
What do they do?
They are an easier way that you would tell an API function on how to do something. Each of the constants have a name and a value assigned to them. This value is represented in hexadecimal form and it is pretty much gibberish to you. However, it is not gibberish to the computer. When telling an API function to do something, some of them may require you to give a constant to tell it how to do something.
For example, the GetAsyncKeyState function will check to see if a key is pressed. How do you tell it which key to check? You give it a constant such as VK_LBUTTON which checks for the mouse left button:
What is happening is that VK_LBUTTON represents a magic number that tells the computer you are referring to the left mouse button. You can also supply the value directly to the function… why not. But that's why constants were created - to help you remember. Who would want to memorize 1000 different hex values and what they do right?
- A colour, in computer graphics, can be represented by an RGB value (red green blue). The RGB is combined with those formula into one single number to represent that colour:
——————–
1.1 Basics
——————–
First, you need the basics of Windows graphics. Just keep the following in mind:
1. a HWND or WINDOW HANDLE is given to EVERY WINDOW. Windows are not just the ones with a blue titlebar, Windows are also buttons, frames, scroll bars etc… All of these have SEPARATE HWNDs. A hwnd is represented by a LONG VARIABLE in VB.
A hwnd can be found using many methods…
One of the most common is FindWindow which has 2 parameters: ClassName & WindowTitle.
Class-names are a certain name that is given to each window created and this is the method that STEALRS2 uses to find the Runescape HWND - Search for the layers of class names.
Most of the time, we won't know the class name, so we can search by using the Window Title. For example, if an open program read "Autominer 3" then the following will find and return the HWND of Autominer 3
However, another method used would be WINDOWFROMPOINT. This API gets the hwnd at a certain x, y position on the screen. We can do this by also declaring the GETCURSORPOS API and POINTAPI structure.
The following code will create a POINTAPI variable, store the coordinates of the current mouse position into the variable and get the window that the X, Y was on. In general, we will get the HWND of the window that our mouse was over.
Macro engines pretty much use this method and they let you "select" a window. There is a button and when the mouse is pressed down (in the Mouse_Down sub), it will change the cursor to a crosshair (Me.MousePointer = vbCrosshair) and then when the mouse is released (Mouse_Up Sub), it will change back the pointer and use the code above to grab the "selected" window.
Also note…
- That the WHOLE SCREEN is represented by a HWND. This HWND can be retrieved using the api GETDESKTOPWINDOW.
2. an HDC is a memory allocation that contains GRAPHICAL INFORMATION. For most windows, you can use the GETDC api to obtain the HDC number. Note that once you are finished with the HDC, you MUST DELETE IT with DELETEDC. Otherwise, you will cause a memory leak flooded with thousands of useless HDCs.
To grab an HDC with GETDC, you have to give the HWND and it will return the HDC for you..
Also note that in order to get the HDC of the ENTIRE screen, you use GETDC(0). However, 0 is not the HWND of the entire screen, it just gives the HDC if you use it with GETDC.
In order to grab graphical information off of a particular HWND, you need to get it's HDC. Then you can use different functions such as GETPIXEL to get the colour.
Study the following:
. One other thing to keep in mind is that COORDINATES (X, Y) represent each pixel on the screen. Coordinate 0,0 is on the top left and it goes as you increase.
There are two types of coordinates: SCREEN COORDINATES and CLIENT COORDINATES.
SCREEN COORDS are basically the coordinates of the ENTIRE SCREEN.
CLIENT COORDS are the coordinates of ONE PARTICULAR HWND.
Note that 0,0 as a SCREEN COORDINATE would be the top, left of your screen.
However, 0,0 of the RS HWND would mean 0,0 of THAT WINDOW.
To convert SCREEN to CLIENT or CLIENT to SCREEN, there are two APIs…
ScreenToClient and CLientTOScreen (lol)
Anyway, both of them accept two parameters: HWND and POINTAPI.
What it does is take the coordinates stored in the POINTAPI variable and convert them to the new one based on the HWND.
For example, this converts a client pixel to the screen pixel.
Now the lol variable's coordinates that were previously 2,3 client coords are changed into their screen coords based on the location of the window.
and it works vice-versa, depending on the function you use.
- Keep in mind that when making macro functions, you should return the coordinate where the colour/bitmap was found as a client coordinate. However, don't forget to change it to a screen coordinate so you can move your mouse there with SetCursorPos API!
4. RECT Tutorial
RECT is a structure/type that contains 4 sub-variables: Left, Top, Bottom, Right.
You declare the structure in your API module and then you create a variable with the RECT type. Then.. you use the GetWindowRect API and tell it: 1. The HWND 2. The RECT variable. It will store the values of Left, Top, Bottom, Right into your variable.
Now why need this?
Well, the Left represents the # of pixels from the hwnd to the left of it's PARENT window (or the window it is in) The Right represents the # of pixels from the right edge to the left of it's PARENT window. The Top represents pixels from the hwnd to the top of the parent and Bottom represents pixels from the bottom of the hwnd to the the top of it's parent window.
Ok that wasn't too clear. But from those values, you can determine the window's height/width by…
1. Height = Subtracting bottom - top, so you get the height
2. Width = subtracting right - left, so you get the width
This is what you need to do if you want to search the entire HWND with a colour function. Most of the time, the parameters of various colour functions require you to type in the height/width of the area you are searching, so you will need RECT to find them for you.
Example:
———————–
2.0 Getdibits…
———————–
Anyway, to start GetDIBits off, we first need to declare the following APIs..
What we are trying to do right now… is to create a function that will use GetDIBits to store the pixels inside an array. Once that's done, you can mess around with the values inside to create your own colour finding functions.
1. Declare the APIs in a module if you have not
2. Open up a new module and enter this:
hwnd - obviously, the window handle of the window you want to get
x - the starting x coordinate of the rectangle to dump from
y - the starting y coordinate…
x2 - the ending x coordinate of the rectangle to dump from
y2 - the ending y coordinate…
If you don't know what the X and Y is… I'll explain. Say you wanted to dump the pixels of a certain area in the HWND, and not the entire thing. And remember that if you pick 2 points on the HWND, it makes a nice box.. One point representing the top, left corner and the other one representing the bottom right.
Those 2 points can be represented by the X, y, X2, Y2. For example, say you wanted to get the pixels of a rectangle inside the HWND from 35,35 to 102, 105 (those 2 points create a rectangle and u want the pixels inside that). Then you would supply X = 35, Y = 35, X2 = 102, Y2 = 105. Get it?
If we wanted to dump the pixels of the ENTIRE WINDOW, then we'd need to give x = 0, y = 0 (to start at the beginning) and x2 = WIDTH of WINDOW and y2 = HEIGHT of WINDOW.
——————-
2.1 Explanation
——————-
In order to use GetDIBits, we have to do the following:
1. Get the HDC of the target HWND.
2. Create our OWN HDC to store OUR OWN GRAPHICAL DATA.
3. Create an EMPTY BITMAP with the dimensions of the target area.
4. Fuse the EMPTY BITMAP with OUR OWN HDC.
5. Copy the pixels from the target HDC to OUR OWN HDC and INTO THE BITMAP we just fused with it.
6. Now we have our own HDC that contains a graphical copy of the target area.
7. Reset the PIXELS() array to a TWO DIMENSIONAL ARRAY THE SIZE OF THE BITMAP. For example, if the bitmap had 50 width, 57 height, the array would become PIXELS(0 to 50, 0 to 57). We want it to be TWO DIMENSIONAL so we can access the coordinates based on an X, Y value.
8. In a BITMAPINFO structure, set some variables that GetDIBits will look at to see how you want the pixels retrieved to be formatted. Many of these variables don't need to be changed such as planes and bit count.. I don't even see how some of the variables will EVER need to be changed anyway.. But we need to set them to their values so GetDIBIts can work.
9. Finally, call the GetDIBits function. This has a lot of parameters.. and they are in the following order:
- The HDC (we put the handle of our own hdc that we made)
- The Bitmap (we put the handle to the bitmap that we fused with our hdc)
- ScanLineToStartFrom (we start scanning from 0 of course, unless we have some weird reason otherwise)
- ScanLineToEndAt (we stop scanning at the height of the bitmap)
- TheBuffer - This is where the data (the pixels) are stored (For this we put PIXELS(0, 0) which is the array that we want them to be in)
- Information - This is a reference to the BITMAPINFO structure that contains the information GetDIBIts needs…
- FormatType - This is how the pixels will be stored.. We would put the DIB_RGB_COLORS constant here because we want it to be stored as RED, GREEN, BLUE not anything else.
10. We clean up ourselves but deleting all the HDCs that were used including the hdc of the target hwnd, the hdc we created and along with that, the bitmap we created.
————–
2.2 Code
————–
Now, change the empty function you had earlier to this. READ THE COMMENTS INSIDE THE CODE, IT CONTAINS ALL THE INFORMATION ABOUT THE FUNCTIONS USED, THE PARAMETERS AND THE RESULT.
You can test the function above with the following code.
Simply use the exact title of a window and it will get the pixels.
[PHP]Theres alot more , just didnt want to paste it all..[/PHP]
———————
1.0 Introduction
———————
GetDIBits is a Windows API that some of you, RS Cheaters, have used to create macroes with.
Typically, the API GetPixel is used, which finds the pixel of a specific HDC on a specific X and Y coordinate. Thus, we could have developed colour searching functions that used GetPixel on all the pixels 1 by 1 in a certain window to find a certain colour.
Some of you have switched to GetDIBits as it is way faster. What this function does is instead of gathering 1 pixel, it takes a "snapshot" of an entire area and gets ALL the pixels. The pixel information are stored inside an ARRAY and you can search for a colour by navigating through the array.
However, GetDIBits is much harder to use (for some people) and that's what this tutorial is about.
Assuming you KNOW the language pretty much and you understand fundamental aspects such as functions and parameters and what an API is…
—————————————
0.0 Section Newb
—————————————
Just to fill in some details… Just in case…
- An API is a function provided by Windows that allows you to interact with it. There are hundreds of these. You declare them in a module or on top of all the code of a form. Usually, you would declare them as Public inside a module so all the parts of your project can use them. You find out the structure of the declaration by opening up your API Viewer.. which you should have.
Example:
Public Declare Function GetBinaryType Lib "kernel32" Alias "GetBinaryTypeA" (ByVal lpApplicationName As String, lpBinaryType As Long) As LongYou don't memorize API declarations.. That's stupid lol. You just grab the ones you need from the API Viewer and paste them in your module. It simply contains information such as the DLL file the function is in, the name, the parameters etc.
- APIs also include structures and constants… which are declared at the top of everything or inside a module as Public so everything can access them.
- A structure/type in VB6 is a custom variable that contains other primitive variables. Ex:
Public Type MYTYPE
MyName As String
MyAge As Integer
MyThis As String
End TypeThus, you could declare a variable as that type…Dim infoAboutMe As MYTYPE
infoAboutMe.MyName = "hello"
infoAboutMe.MyThis ="yaa"The POINTAPI type is just a variable that contains two sub-variables: X and Y… which simply represent coordinates. It is part of the API because many API functions rely on POINTAPI to return their results to you.
- A constant is a magic number also in the API that you can get from the API Viewer.. It's in the form or something like this:
Public Const ME = &H5315
Public Const LOL = 0&Again, you declare them as Public in a module or on top of everything inside a form.
What do they do?
They are an easier way that you would tell an API function on how to do something. Each of the constants have a name and a value assigned to them. This value is represented in hexadecimal form and it is pretty much gibberish to you. However, it is not gibberish to the computer. When telling an API function to do something, some of them may require you to give a constant to tell it how to do something.
For example, the GetAsyncKeyState function will check to see if a key is pressed. How do you tell it which key to check? You give it a constant such as VK_LBUTTON which checks for the mouse left button:
If GetAsyncKeyState(VK_LBUTTON) = 1 Then Msgbox "Yay!"What is happening is that VK_LBUTTON represents a magic number that tells the computer you are referring to the left mouse button. You can also supply the value directly to the function… why not. But that's why constants were created - to help you remember. Who would want to memorize 1000 different hex values and what they do right?
- A colour, in computer graphics, can be represented by an RGB value (red green blue). The RGB is combined with those formula into one single number to represent that colour:
65536 * R + 256 * G + 1 * B——————–
1.1 Basics
——————–
First, you need the basics of Windows graphics. Just keep the following in mind:
1. a HWND or WINDOW HANDLE is given to EVERY WINDOW. Windows are not just the ones with a blue titlebar, Windows are also buttons, frames, scroll bars etc… All of these have SEPARATE HWNDs. A hwnd is represented by a LONG VARIABLE in VB.
A hwnd can be found using many methods…
One of the most common is FindWindow which has 2 parameters: ClassName & WindowTitle.
Class-names are a certain name that is given to each window created and this is the method that STEALRS2 uses to find the Runescape HWND - Search for the layers of class names.
Most of the time, we won't know the class name, so we can search by using the Window Title. For example, if an open program read "Autominer 3" then the following will find and return the HWND of Autominer 3
Dim HWND As Long
HWND = FindWindow(vbNullString, "Autominer 3")
'The VbNullString is used to represent that we do not know the class name.However, another method used would be WINDOWFROMPOINT. This API gets the hwnd at a certain x, y position on the screen. We can do this by also declaring the GETCURSORPOS API and POINTAPI structure.
The following code will create a POINTAPI variable, store the coordinates of the current mouse position into the variable and get the window that the X, Y was on. In general, we will get the HWND of the window that our mouse was over.
Dim h As PointAPI, HWND
GetCursorPos h
HWND = WindowFromPoint(h.x, h.y)
Macro engines pretty much use this method and they let you "select" a window. There is a button and when the mouse is pressed down (in the Mouse_Down sub), it will change the cursor to a crosshair (Me.MousePointer = vbCrosshair) and then when the mouse is released (Mouse_Up Sub), it will change back the pointer and use the code above to grab the "selected" window.
Also note…
- That the WHOLE SCREEN is represented by a HWND. This HWND can be retrieved using the api GETDESKTOPWINDOW.
2. an HDC is a memory allocation that contains GRAPHICAL INFORMATION. For most windows, you can use the GETDC api to obtain the HDC number. Note that once you are finished with the HDC, you MUST DELETE IT with DELETEDC. Otherwise, you will cause a memory leak flooded with thousands of useless HDCs.
To grab an HDC with GETDC, you have to give the HWND and it will return the HDC for you..
Dim HDC as Long
HDC = GetDC( hwnd number here... )
DeleteDC HDC
Also note that in order to get the HDC of the ENTIRE screen, you use GETDC(0). However, 0 is not the HWND of the entire screen, it just gives the HDC if you use it with GETDC.
In order to grab graphical information off of a particular HWND, you need to get it's HDC. Then you can use different functions such as GETPIXEL to get the colour.
Study the following:
Dim HDC As Long, HWND As Long
'Your task bar's class name is "shell_traywnd"
HWND = FindWindow("shell_traywnd", vbNullString)
HDC = GetDC(HWND)
'Use getpixel - give it the hdc + the x and y coordinates
Msgbox "The Colour At 53, 53 is " & GetPixel(HDC, 1, 1)
DeleteDC HDC. One other thing to keep in mind is that COORDINATES (X, Y) represent each pixel on the screen. Coordinate 0,0 is on the top left and it goes as you increase.
There are two types of coordinates: SCREEN COORDINATES and CLIENT COORDINATES.
SCREEN COORDS are basically the coordinates of the ENTIRE SCREEN.
CLIENT COORDS are the coordinates of ONE PARTICULAR HWND.
Note that 0,0 as a SCREEN COORDINATE would be the top, left of your screen.
However, 0,0 of the RS HWND would mean 0,0 of THAT WINDOW.
To convert SCREEN to CLIENT or CLIENT to SCREEN, there are two APIs…
ScreenToClient and CLientTOScreen (lol)
Anyway, both of them accept two parameters: HWND and POINTAPI.
What it does is take the coordinates stored in the POINTAPI variable and convert them to the new one based on the HWND.
For example, this converts a client pixel to the screen pixel.
Dim HWND As Long, lol As PointAPI
HWND = FindWindow("Shell_Traywnd", vbNullString)
lol.x = 2
lol.y = 3
'// Coord 2, 3 as a client coordinate for the HWND
'//Now to convert to screen coordinates
ClientToScreen HWND, lolNow the lol variable's coordinates that were previously 2,3 client coords are changed into their screen coords based on the location of the window.
and it works vice-versa, depending on the function you use.
- Keep in mind that when making macro functions, you should return the coordinate where the colour/bitmap was found as a client coordinate. However, don't forget to change it to a screen coordinate so you can move your mouse there with SetCursorPos API!
4. RECT Tutorial
RECT is a structure/type that contains 4 sub-variables: Left, Top, Bottom, Right.
You declare the structure in your API module and then you create a variable with the RECT type. Then.. you use the GetWindowRect API and tell it: 1. The HWND 2. The RECT variable. It will store the values of Left, Top, Bottom, Right into your variable.
Now why need this?
Well, the Left represents the # of pixels from the hwnd to the left of it's PARENT window (or the window it is in) The Right represents the # of pixels from the right edge to the left of it's PARENT window. The Top represents pixels from the hwnd to the top of the parent and Bottom represents pixels from the bottom of the hwnd to the the top of it's parent window.
Ok that wasn't too clear. But from those values, you can determine the window's height/width by…
1. Height = Subtracting bottom - top, so you get the height
2. Width = subtracting right - left, so you get the width
This is what you need to do if you want to search the entire HWND with a colour function. Most of the time, the parameters of various colour functions require you to type in the height/width of the area you are searching, so you will need RECT to find them for you.
Example:
HWND = ....
Dim Dimensions As RECT
GetWindowRect HWND, Dimensions
Msgbox "Height is " & Dimension.Bottom - Dimension.Top
Msgbox "Width is " & Dimension.Right - Dimension.Left———————–
2.0 Getdibits…
———————–
Anyway, to start GetDIBits off, we first need to declare the following APIs..
Option Explicit
Declare Function SetDIBitsToDevice Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal dx As Long, ByVal dy As Long, ByVal SrcX As Long, ByVal SrcY As Long, ByVal Scan As Long, ByVal NumScans As Long, Bits As Any, ByRef BitsInfo As BITMAPINFO, ByVal wUsage As Long) As Long
Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Declare Function StretchBlt Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long
Declare Function SetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal crColor As Long) As Long
Declare Function GetObject Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Declare Function CreateDIBSection Lib "gdi32" (ByVal hdc As Long, pBitmapInfo As BITMAPINFO, ByVal un As Long, ByVal lplpVoid As Long, ByVal handle As Long, ByVal dw As Long) As Long
Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Declare Function StretchDIBits Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal dx As Long, ByVal dy As Long, ByVal SrcX As Long, ByVal SrcY As Long, ByVal wSrcWidth As Long, ByVal wSrcHeight As Long, lpBits As Any, lpBitsInfo As BITMAPINFO, ByVal wUsage As Long, ByVal dwRop As Long) As Long
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Type POINTAPI
x As Long
y As Long
End Type
Type BITMAP '14 bytes
bmType As Long
bmWidth As Long
bmHeight As Long
bmWidthBytes As Long
bmPlanes As Integer
bmBitsPixel As Integer
bmBits As Long
End Type
Type BITMAPINFOHEADER '40 bytes
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type
Type RGBQUAD
rgbBlue As Byte
rgbGreen As Byte
rgbRed As Byte
rgbReserved As Byte
End Type
Type BITMAPINFO
bmiHeader As BITMAPINFOHEADER
bmiColors As RGBQUAD
End Type
Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Const DIB_RGB_COLORS = 0&
Const BI_RGB = 0&
What we are trying to do right now… is to create a function that will use GetDIBits to store the pixels inside an array. Once that's done, you can mess around with the values inside to create your own colour finding functions.
1. Declare the APIs in a module if you have not
2. Open up a new module and enter this:
Public PIXELS() As RGBQUAD
Public Function DumpPixels(hwnd As Long, x as long, y as long, x2 as long, y2 as long)
End Function
What we have done is just created an empty function and a global array called PIXELS(). The function is where we will build our GetDIBits pixel "dumper… It accepts the following parameters:hwnd - obviously, the window handle of the window you want to get
x - the starting x coordinate of the rectangle to dump from
y - the starting y coordinate…
x2 - the ending x coordinate of the rectangle to dump from
y2 - the ending y coordinate…
If you don't know what the X and Y is… I'll explain. Say you wanted to dump the pixels of a certain area in the HWND, and not the entire thing. And remember that if you pick 2 points on the HWND, it makes a nice box.. One point representing the top, left corner and the other one representing the bottom right.
Those 2 points can be represented by the X, y, X2, Y2. For example, say you wanted to get the pixels of a rectangle inside the HWND from 35,35 to 102, 105 (those 2 points create a rectangle and u want the pixels inside that). Then you would supply X = 35, Y = 35, X2 = 102, Y2 = 105. Get it?
If we wanted to dump the pixels of the ENTIRE WINDOW, then we'd need to give x = 0, y = 0 (to start at the beginning) and x2 = WIDTH of WINDOW and y2 = HEIGHT of WINDOW.
——————-
2.1 Explanation
——————-
In order to use GetDIBits, we have to do the following:
1. Get the HDC of the target HWND.
2. Create our OWN HDC to store OUR OWN GRAPHICAL DATA.
3. Create an EMPTY BITMAP with the dimensions of the target area.
4. Fuse the EMPTY BITMAP with OUR OWN HDC.
5. Copy the pixels from the target HDC to OUR OWN HDC and INTO THE BITMAP we just fused with it.
6. Now we have our own HDC that contains a graphical copy of the target area.
7. Reset the PIXELS() array to a TWO DIMENSIONAL ARRAY THE SIZE OF THE BITMAP. For example, if the bitmap had 50 width, 57 height, the array would become PIXELS(0 to 50, 0 to 57). We want it to be TWO DIMENSIONAL so we can access the coordinates based on an X, Y value.
8. In a BITMAPINFO structure, set some variables that GetDIBits will look at to see how you want the pixels retrieved to be formatted. Many of these variables don't need to be changed such as planes and bit count.. I don't even see how some of the variables will EVER need to be changed anyway.. But we need to set them to their values so GetDIBIts can work.
9. Finally, call the GetDIBits function. This has a lot of parameters.. and they are in the following order:
- The HDC (we put the handle of our own hdc that we made)
- The Bitmap (we put the handle to the bitmap that we fused with our hdc)
- ScanLineToStartFrom (we start scanning from 0 of course, unless we have some weird reason otherwise)
- ScanLineToEndAt (we stop scanning at the height of the bitmap)
- TheBuffer - This is where the data (the pixels) are stored (For this we put PIXELS(0, 0) which is the array that we want them to be in)
- Information - This is a reference to the BITMAPINFO structure that contains the information GetDIBIts needs…
- FormatType - This is how the pixels will be stored.. We would put the DIB_RGB_COLORS constant here because we want it to be stored as RED, GREEN, BLUE not anything else.
10. We clean up ourselves but deleting all the HDCs that were used including the hdc of the target hwnd, the hdc we created and along with that, the bitmap we created.
————–
2.2 Code
————–
Now, change the empty function you had earlier to this. READ THE COMMENTS INSIDE THE CODE, IT CONTAINS ALL THE INFORMATION ABOUT THE FUNCTIONS USED, THE PARAMETERS AND THE RESULT.
Public PIXELS() As RGBQUAD
Public Function DumpPixels(hwnd As Long, x as long, y as long, x2 as long, y2 as long)
Dim HDC As Long '//The HDC of the target HWND
Dim MDC As Long '//The HDC we are going to create
Dim MBmap As Long '//The bitmap we are going to create
Dim MInfo As BITMAPINFO '//The info getdibits needs
Dim HEIGHT1 As Long '//Just a number to represent the image height
Dim WIDTH1 As Long '//A number to represent the image width
'//Start by getting the HDC of the target HWND
HDC = GetDC(hwnd)
'//Then create our own HDC with CreateCompatibleDC
'//This HDC must be compatible with the HDC of the target HWND
'//We supply the HDC it needs to be compatible with as a parameter
'//It returns the handle to the HDC we created inside MDC
MDC = CreateCompatibleDC(HDC)
'//We are subtracting x2 - x and y2 - y because if we subtract
'//the second coordinate by the first, we get the width/height..
HEIGHT1 =y2 - y '//This is the height of the target image
WIDTH1 = x2 - x '//This is the width of the target image
'//Now we create an empty bitmap with the size
'//of the area we are dumping pixels from
'//Then we store the handle to that bitmap inside MBmap
'//The parameters for CreateCompatibleBitmap are:
'//1. The HDC it must be compatible with (the target hwnd's HDC)
'//2. The Width of the bitmap
'//3. The Height of the bitmap
MBmap = CreateCompatibleBitmap(HDC, WIDTH1, HEIGHT1)
'//Now we have to fuse the bitmap into the HDC we created
'//so we can store an image inside it.
'//The SelectObject API puts the SECOND PARAMETER object
'//into the FIRST PARAMETER object. In this case...
'//The second param is the BITMAP OBJECT that we are placing
'//inside the first HDC OBJECT.
SelectObject MDC, MBmap
'//Now we use the BITBLT API to copy graphical content
'//of ONE HDC to another HDC. It has these parameters:
'//1. TargetDC - where to copy the contents to
'//2. TargetX - an X coordinate to represent where it is pasted
'//3. TargetY - a Y coordinate to represent where it is pasted
'//4. TargetWidth - represents the width of the copied image
'// starting from TargetX
'//5. TargetHeight - same thing as TargetWidth
'//6. SourceDC - where to copy the contents FROM
'//7. SourceX - an X coordinate to start copying from
'//8. SOurceY - a Y coordinate to start copying from
'//9. RasterMode - how the ending image will look like. In this
'// case, we will use vbSrcCopy, which represents that
'// the image is copied directly without any colour combination etc.
BitBlt MDC, 0, 0, WIDTH1, HEIGHT1, HDC, x, y, vbSrcCopy
'//We have copied HDC (target hwnd's HDC) to MDC (our own HDC)
'//the image copied has been formatted to the required size
'//and also the appropriate x, y start-copy coordinates.
'//Now we have to re-make the array of PIXELS() to make the
'//number of pixels fit inside.
'//We use the ReDim command to re-set the array dimensions.
'//We redim it to the HEIGHT and WIDTH of the BITMAP.
ReDim PIXELS(0 to WIDTH1 - 1, 0 to HEIGHT1 - 1)
'//Note that there is a -1 because we start counting from 0 in the array.
'//However, we start counting from 1 when counting the width/height
'//So we reduce it by 1.
'//There is a MAJOR issue if you do not do this correctly. More later.
'//Now we set the information GetDIBits needs...
'//We set the MInfo BITMAPINFO structure's BmiHeader
'//The following values that are changed are mandatory
'//Everything else is left at 0.
With MInfo.BmiHeader
.biSize = 40 '//Size of structure variable.. Always 40.
.biWidth = WIDTH1 '//Width of bitmap
.biHeight = -HEIGHT1 '//Height of bitmap..
'//it is negative becuz height is backwards
.biPlanes = 1 '//There is only 1 plane...
.biBitCount = 32 '//Always a 32 bit-count image..
'//otherwise the colours won't be right
.biCompression = BI_RGB
End With
'//Finally we make a call to GetDIBIts with the following parameters:
'//HDC - the hdc where the pixels will be read from
'//Bitmap - the bitmap inside the hdc where the pixels will be read from
'//Starting ScanLine - 0.. where we start scanning
'//ENding ScanLine - where we stop scanning..
'//Buffer - the variable where the pixels will be stored
'//BitInfo - the information required inside the BITMAPINFO strucutre
'//ColourMethod - In this case, it's DIB_RGB_COLORS for Red/Green/Blue
GetDIBits MDC, MBmap, 0, HEIGHT1, Pixels(0, 0), MInfo, DIB_RGB_COLORS
'//Delete MDC and HDC from memory
DeleteDC MDC
DeleteDC HDC
'//In the end, GetDIBIts will have wrote to Pixels(0, 0) the colours
'//of each pixel in the hwnd supplied
End Function
You can test the function above with the following code.
Simply use the exact title of a window and it will get the pixels.
Public Function useTheAboveFunction()
Const TITLE = "<PUT TITLE HERE>"
Dim hwnd as long, winDimensions As RECT
hwnd = FindWindow(vbNullString, TITLE)
'Find the left, top, right, bottom values
'if we subtract bottom - top, we get the HEIGHT
'and right - left is the WIDTH
'We use the height and width as the values for x2, y2
GetWindowRect hwnd, winDimensions
DumpPixels hwnd, 0, 0, winDimensions.RIght - winDimensions.Left, winDimensions.Bottom - winDimensions.Top
End Function
[PHP]Theres alot more , just didnt want to paste it all..[/PHP]