sdlangers Posted June 27, 2003 Posted June 27, 2003 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: 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 i've 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 Quote
*Experts* Volte Posted June 27, 2003 *Experts* Posted June 27, 2003 There's 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 don't think that will be necessary). BTW, those GC.Collect()'s aren't needed. The GC won't collect objects until you are completely done with them, so it won't matter. You need to use the 'Dispose' method of the objects before the garbage collector will touch them (if you don't use it, the GC will pick them up when the object is destroyed). Quote
sdlangers Posted June 27, 2003 Author Posted June 27, 2003 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 Quote
*Experts* Volte Posted June 27, 2003 *Experts* Posted June 27, 2003 When a loop is running continuously, your CPU % will most likely jump to near 100%. There really isn't 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 wouldn't require a DoEvents, so it may be quicker. Quote
sdlangers Posted June 28, 2003 Author Posted June 28, 2003 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? Quote
*Experts* Volte Posted June 28, 2003 *Experts* Posted June 28, 2003 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). Quote
sdlangers Posted June 28, 2003 Author Posted June 28, 2003 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 Quote
*Experts* Volte Posted June 28, 2003 *Experts* Posted June 28, 2003 Well, if you are talking strictly about the code you pasted above, it doesn't look like there are any GDI objects being left in memory. You might try calling ReleaseDC on that dcSource object though. I'm not sure if not releasing DCs will cause Out of Memory errors or not. Quote
*Gurus* divil Posted June 29, 2003 *Gurus* Posted June 29, 2003 Couldn't 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. Quote MVP, Visual Developer - .NET Now you see why evil will always triumph - because good is dumb. My free .NET Windows Forms Controls and Articles
sdlangers Posted June 30, 2003 Author Posted June 30, 2003 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... ' 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 Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.