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
DovbermanAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Shane Russell2nd Line Desktop SupportCommented:
I think this will help you :

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

If you still need help post back :)
DovbermanAuthor Commented:
<<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

Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics TeacherCommented:
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
Your Guide to Achieving IT Business Success

The IT Service Excellence Tool Kit has best practices to keep your clients happy and business booming. Inside, you’ll find everything you need to increase client satisfaction and retention, become more competitive, and increase your overall success.

Erick37Commented:
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.
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics TeacherCommented:
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...

=)
DovbermanAuthor Commented:
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
Erick37Commented:
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
DovbermanAuthor Commented:
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
DovbermanAuthor Commented:
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?
Erick37Commented:
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
DovbermanAuthor Commented:
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
Erick37Commented:
It takes a bit of effort to force a window to the top, but it can be done.

"Microsoft changed the rules with Win98 and Windows 2000 ("The OS formerly known as NT5"). The SetForegroundWindow API can no longer be used directly to take focus away from another application. This demo offers my own implementation of ForceForegroundWindow -- a VB function that uses AttachThreadInput together with SetForegroundWindow -- to, well, force the issue..."

http://www.classicvb.net/samples/project.asp?id=forcefore

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
DovbermanAuthor Commented:
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic Classic

From novice to tech pro — start learning today.