Link to home
Start Free TrialLog in
Avatar of Dovberman
DovbermanFlag for United States of America

asked on

How to capture a rectangular area of a window

I know the handle of a window. I also know the coordinates of the rectangular region of the window that I would like to capture. Once the region is captured, I would like to create a bitmap in memory of the captured region.

Here is where I am:

hObjectDC = CreateRectRgn(270, 188, 285, 224) 'Handle to caputred region

hCaptureDC = CreateCompatibleDC(hObjectDC)

hCaptureBitmap = CreateCompatibleBitmap(hCaptureDC, 15, 36)

This code fails because the captured region is not a window
IsWindow (hObjectDC) returns false

I then need to store the bitmap bits into an array.

Could you point me to an example where a common window like calc.exe is used.
Perhaps the example could show how to capture a region of the calculator window.
(Not a specific button or object)


Thanks,

Dovberman
Avatar of Shane Russell
Shane Russell
Flag of United Kingdom of Great Britain and Northern Ireland image

I think this will help you :

http://support.microsoft.com/kb/q161299/

If you still need help post back :)
Avatar of Dovberman

ASKER

<<Here is where I am:

hObjectDC = CreateRectRgn(270, 188, 285, 224) 'Handle to caputred region

hCaptureDC = CreateCompatibleDC(hObjectDC)

hCaptureBitmap = CreateCompatibleBitmap(hCaptureDC, 15, 36)

This code fails because the captured region is not a window
IsWindow (hObjectDC) returns false>>

I have already reviewed the article you referenced.

The article does not use CreateRectRgn which captures a specific rectanglular segment of the window. It is CreateRectRgn which returns a handle, but does not recognize the region as a window.

I need an example that specifically addresses the CreateRectRgn function.

Thanks,

Dovberman

Avatar of Mike Tomlinson
Dovberman,

What is the end goal here?  Do you really need CreateRectRgn() to capture a specific region of a window?  (The link gecko has given demonstrates that you don't.)  Do you really need the bitmap bits in an array or will a Picture object do?  There may be other ways of going about this!

Give us a bigger picture and tell us more about what you are doing...

~IM
CreateRectRgn returns a handle to a region.
CreateCompatibleDC can only use the handle to a device context.
You cannot use CreateRectRgn with CreateCompatibleDC to get a screen capture.
Thank you Erick37 for that clarification.  I was pretty sure the approach being taken wasn't quite right but I'm no GDI expert!  Hence the roundabout wording in my questions above...

=)
OK, here is the overview.  I have developed an application that lists odds of drawing to specific hands when playing hold'em at an on line gaming site.  The gaming site displays a table on which card images appear to represent cards that are dealt as community cards.

I need to capture the card images as memory bitmaps. Once this is done, I can compare the captured images to a catalog of 52 images. This will tell me which card has been dealt.

I know the x,y coordinates to the top left corner of each card image on the gaming table. I know the handle of the game window.  I also know the card image length and width.

I thought that each card image was defined as a rectangular area. If this is true , then I assumed that CreateRectRgn would define each card.

Anyway, given this background, how do I capture each card image.  I have picture controls on my application form to hold the captured images.

Thanks,

Dovberman
The easiest way I can think of is to BitBlt right from the screen to your picturebox.  Like any screen capture, this will work only if the area you are blitting from is currently visible on the screen.

Simple example omitting the API declarations:

Dim hWndCalculator As Long
Dim hDCScreen As Long
Dim pt As POINTAPI

hWndCalculator = FindWindow(vbNullString, "Calculator")

If hWndCalculator <> 0 Then
    'get the screen DC
    hDCScreen = GetDC(0)
   
    'get the upper left coordinate of calculator as a reference point
    Call ClientToScreen(hWndCalculator, pt)
    'blit the image to your Picturebox
    'pt.x and pt.y is the upper left of the client area... add offsets as needed
    Call BitBlt(Picture1.hDC, 0, 0, 50, 50, hDCScreen, pt.x, pt.y, vbSrcCopy)
   
End If
Sounds like a winner.

I was unaware of the API call that returns the upper left corner coordinates of the window that contains the region I want to capture.

<<'get the upper left coordinate of calculator as a reference point
    Call ClientToScreen(hWndCalculator, pt)>>

I will try this.

Thanks,

Dovberman
I believe we are almost there.

I get no errors.  However the picture box control remains empty
The pictureBox has an HDC

I am not clear on the coordinate representation.

Here is my code:

===============
Private Sub cmdCapture_Click()
   
    Dim hwndSelected As Long
    Dim strWindowName As String
    Dim hdcCapture As Long
    Dim hdcScreen As Long
    Dim StartPoint As POINTAPI
    Dim lngStartPoint As Long
    Dim lngBitBltRet As Long
   
   hwndSelected = CLng(lstDeskTop.SelectedItem.SubItems(1))
   If hwndSelected <> 0 Then
        'get the screen DC
        hdcScreen = GetDC(0)
       
        'get the upper left coordinate of calculator as a reference point
        StartPoint.x = 0
        StartPoint.y = 0
       
        lngStartPoint = ClientToScreen(hwndSelected, StartPoint)
        'blit the image to your Picturebox
        'pt.x and pt.y is the upper left of the client area... add offsets as needed
        lngBitBltRet = BitBlt(picCapture.hdc, 0, 0, 50, 50, hdcScreen, StartPoint.x, StartPoint.y, vbSrcCopy)
    End If
   
    'From API_Guide 3.7
    '· nWidth
'Specifies the logical width of the source and destination rectangles.

'· nHeight
'Specifies the logical height of the source and the destination rectangles.

'· hdcSrc
'Identifies the source device context.

'· nXSrc
'Specifies the logical x-coordinate of the upper-left corner of the source rectangle.

'· nYSrc
'Specifies the logical y-coordinate of the upper-left corner of the source rectangle.
   
End Sub

========================

Do I need expressions to get the logical coordinates and dimensions ?

What is meant by the term 'logical' in this context?
Logical units are the unit of measure for a device context.  In VB, the default is twips.  In the API functions the default unit is pixels.  Any time you use API functions, use pixels.

Try setting the Autoredraw property of the picturebox = True.
Then refresh the picturebox after the bitblt.

picCapture.Autoredraw = True
Call BitBlt(picCapture.hDC, ...
picCapture.Refresh
It is working. The autoredraw and Refresh methods were not the issue. However, this is good management code.

The region to be captured was covered by a different window.

Which API call places the source window on top ?

Thanks,

Dovberman
ASKER CERTIFIED SOLUTION
Avatar of Erick37
Erick37
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
This brings the desired window to the top.

Module constants:

Public Const HWND_TOPMOST = -1
Public Const HWND_NOTOPMOST = -2
Public Const SWP_NOSIZE = &H1
Public Const SWP_NOMOVE = &H2
Public Const SWP_NOACTIVATE = &H10
Public Const SWP_SHOWWINDOW = &H40

Public Declare Function SetWindowPos Lib "user32" _
(ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _
ByVal x As Long, ByVal y As Long, _
ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long

 'Bring source window to top
'hwndSelected- handle of the window you wish to force to the top

 SetWindowPos hwndSelected, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE Or _ SWP_SHOWWINDOW Or SWP_NOMOVE Or SWP_NOSIZE

Thanks,

Dovberman