waiting for a pixel to change

sdlangers

Well-known member
Joined
Dec 3, 2002
Messages
118
Hi All,

I was wondering if anyone knew a good way to detect a change in a pixel.

i.e. I have code that uses bitblt to capture a pixel on the screen as follows:

Code:
    Public Function checkPixel(ByVal X As Integer, ByVal Y As Integer, ByVal col() As Color, ByVal errRange As Integer) As Boolean
        Dim imgPixel As Image
        Dim bmpPixel As Bitmap
        Dim gr As Graphics
        Dim dcDest As IntPtr, dcSource As IntPtr
        Dim i As Integer, j As Integer

         initialize image
        imgPixel = New Bitmap(1, 1)
         get handle to new image
        gr = Graphics.FromImage(imgPixel)
        dcDest = gr.GetHdc()
         get handle to desktop
        dcSource = GetWindowDC(GetDesktopWindow())
         copy pixel to image
        BitBlt(dcDest, 0, 0, 1, 1, dcSource, X, Y, SRCCOPY)
         release handle
        gr.ReleaseHdc(dcDest)

         process image
        bmpPixel = New Bitmap(imgPixel)

         Check all colors in array
        For i = 0 To UBound(col)
            If isColorEqual(bmpPixel.GetPixel(0, 0), col(i), errRange) Then
                bmpPixel = Nothing
                System.GC.Collect()
                checkPixel = True
                Exit Function
            End If
        Next


        bmpPixel = Nothing
        System.GC.Collect()
        checkPixel = False

    End Function

and what ive been doing is simply putting this in a while loop and passing it the color of the pixel im looking for it to change too and waiting for it to return true.

It seems there should be a smoother/easier way that would be easier on resources ? :)

any thoughts/ideas would be great

also any advise on memory management/clean up techniques in vb.net would ge great (i know c# is better for this, but the app is in vb.net)


thanks
 
Theres no handler to do it, really... I think your way is probably the only decent way to do it (unless you want to try Threading, but I dont think that will be necessary).

BTW, those GC.Collect()s arent needed. The GC wont collect objects until you are completely done with them, so it wont matter. You need to use the Dispose method of the objects before the garbage collector will touch them (if you dont use it, the GC will pick them up when the object is destroyed).
 
also, the while loop i have calling that basically runs continuously until the pixel changes - i have a delay on the thread in the loop and an application.doevents

are there any other good ways/techniques to keep CPU % down?

thanks again
 
When a loop is running continuously, your CPU % will most likely jump to near 100%. There really isnt any way to avoid that. It may not affect performance, but it will kick the CPU usage gauge up.

You could make a second thread in your application and put the loop code in that. Then you wouldnt require a DoEvents, so it may be quicker.
 
ok - i think the way i have it should do then

on to the next and hopefully final problem..

the progam i wrote runs perfectly for about 2-3 hours and the memory and CPU% stay low throughout.

but then after a couple of hours, the API calls (getdesktopwindow and/or bitblt) return an

invalid parameter

error or sometimes out of memory error

any ideas what could be causing that?
 
It sounds like you are probably not cleaning up all of your GDI objects. Make sure you call DeleteObject on all objects you create (pens, brushes, etc), and DeleteDC on all the DCs that you create (not the ones you get by way of GetDC or whatever, thought you should call ReleaseDC() on those to release them).
 
thanks for all your help volte force..

its basically just that function that i listed above at the start of thread.

is there anywhere in that code where i should be using deleteobject or deleteDC ?

thanks again
 
Well, if you are talking strictly about the code you pasted above, it doesnt look like there are any GDI objects being left in memory.

You might try calling ReleaseDC on that dcSource object though. Im not sure if not releasing DCs will cause Out of Memory errors or not.
 
Couldnt you use the GetPixel api instead? That would avoid having to create bitmaps and use bitblt, you could just read the pixel straight from the screen.
 
thanks divil - that sounds like itd be better on resources etc..

but now i cant get that working right :(

ive a feeling its something to do with the API declarations - the types of the parameters maybe?

heres the code...

Code:
     GDI Functions
    Public Declare Function GetPixel Lib "gdi32" Alias "GetPixel" (ByVal hdc As IntPtr, ByVal x As Integer, ByVal y As Integer) As Integer

     User32 Functions
    Public Declare Function GetDesktopWindow Lib "user32.dll" Alias "GetDesktopWindow" () As IntPtr
    Public Declare Function GetWindowDC Lib "user32.dll" Alias "GetWindowDC" (ByVal ptr As Int32) As IntPtr
    Public Declare Function ReleaseDC Lib "user32.dll" Alias "ReleaseDC" (ByVal hWnd As IntPtr, ByVal hDc As IntPtr) As IntPtr

    Public Function checkPixel(ByVal X As Integer, ByVal Y As Integer) As Integer
        Dim hDC As IntPtr
         Get Desktop hDC
        hDC = GetWindowDC(GetDesktopWindow().ToInt32)
         Get Pixel
        checkPixel = GetPixel(hDC, X, Y)
         Release Desktop hDC
        ReleaseDC(GetDesktopWindow(), hDC)
    End Function

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim c As New Color()
        Dim i As Integer
         get color integer value
        i = checkPixel(100, 50)
         convert to color and display
        c = Color.FromArgb(i)
        MsgBox("Color = " & CStr(i) & " - " & c.R & ", " & c.G & ", " & c.B)
    End Sub

thanks for yer help guys
 
Back
Top