Solved

getpixel

Posted on 2004-03-29
13
1,956 Views
Last Modified: 2012-06-27
this is sorta urgent

okay... uhm  I looked through a LOT of google groups messages on how to get the color of a pixel at a certain coordinate(preferably a fast way).  I found a bunch of stuff about using the windows api in gdi.dll.  I've tried to use this in visual basic .NET and failed... and failed... and you get the idea.  

I hear there's an "object.point" method of doing this too.  If this is faster for the computer at run time please tell me.

I really just need a sample code of how to get it to work.
0
Comment
Question by:8_digits
  • 3
  • 3
  • 2
  • +2
13 Comments
 
LVL 5

Accepted Solution

by:
Pi7 earned 168 total points
ID: 10702860
Check this link.It'll probably help
        http://www.mentalis.org/apilist/GetPixel.shtml

Regards,
Pi7
0
 
LVL 17

Assisted Solution

by:zzzzzooc
zzzzzooc earned 166 total points
ID: 10703687
Here's an example of getting the pixel color of wherever the mouse cursor is (pretty fast). You didn't specify what you wanted to get the pixel of so this'll cover the entire desktop.



Form1:
------------

Option Explicit

Private Type POINTAPI
    X As Long
    Y As Long
End Type

Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long

Private lDesktopDC As Long
Private Sub Form_Load()
    lDesktopDC = GetDC(0)
    Timer1.Interval = 100
    Timer1.Enabled = True
End Sub
Private Sub Form_Unload(Cancel As Integer)
    Call ReleaseDC(0, lDesktopDC)
End Sub
Private Sub Timer1_Timer()
    Dim tPt As POINTAPI, lRGB As Long
    Call GetCursorPos(tPt)
    lRGB = GetPixel(lDesktopDC, tPt.X, tPt.Y)
    If lRGB <> -1 Then
        Me.BackColor = lRGB
    End If
End Sub
0
 

Author Comment

by:8_digits
ID: 10707763
Okay...  there were a few incompatibilities with zzzzzooc's solution although it will probably work in VB 6.0 or maybe a really early version of VB.NET.  It seems that the "type" is no longer allowed(as in: refuses to compile) so I substituted structure instead.  I've also converted the RGB color to an integer(32bit) because of another problem.  " Value of type 'Long' cannot be converted to 'System.Drawing.Color'."---  I couldn't find a way to assign a long value to type color.
*sigh*  here's your code that I modified

    Private Structure POINTAPI
        Public X As Long
        Public Y As Long
    End Structure

    Private Declare Function GetCursorPos Lib "user32" (ByVal lpPoint As POINTAPI) As Long
    Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long) As Long
    Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long

    Private lDesktopDC As Long
    Private Sub Form_Load()
        lDesktopDC = GetDC(0)
        Timer1.Interval = 100
        Timer1.Enabled = True
    End Sub
    Private Sub Form_Unload(ByVal Cancel As Integer)
        Call ReleaseDC(0, lDesktopDC)
    End Sub
    Private Sub Timer1_Timer()
        Dim tPt As POINTAPI, lRGB As Long
        Call GetCursorPos(tPt)
        lRGB = GetPixel(lDesktopDC, tPt.X, tPt.Y)
        If lRGB <> -1 Then
            Me.BackColor = Color.FromArgb(cint(lRGB))
        End If
    End Sub
0
 

Author Comment

by:8_digits
ID: 10707825
Pi7.  after searching the internet for over 4 hours I came across that site 6 or maybe 7 times.  It seems to be a very popular site, but the only getpixel in vb.net is in the bitmap object.  I don't know if it's posible for me to quickly assign a value.  Sorry if I come off as a bit irritable.  I've had no rest int the past day.
0
 
LVL 27

Assisted Solution

by:Ark
Ark earned 166 total points
ID: 10709641

Private Sub Timer1_Timer()
    Static lX As Long, lY As Long
    On Local Error Resume Next
    Dim P As POINTAPI, h As Long, hD As Long, R As Long
    GetCursorPos P
'Skip all opeartions if cursor position didn't change (to make thing faster)
    If P.x = lX And P.y = lY Then Exit Sub
    lX = P.x: lY = P.y
'Get window under cursor and it dc
    h = WindowFromPoint(lX, lY)
    hD = GetDC(h)
    ScreenToClient h, P
    R = GetPixel(hD, P.x, P.y)
'GetPixel retunrns CLR_INVALID(-1) for non-client area (caption, icon, etc)
'Here is work around
    If R = -1 Then
        BitBlt Me.hDC, 0, 0, 1, 1, hD, P.x, P.y, vbSrcCopy
        R = Me.Point(0, 0)
'or    R = GetPixel(Me.hDC, P.x, P.y)
    Else
        Picture1.PSet (0, 0), R
    End If
    ReleaseDC h, hD
    Me.BackColor = Color.FromArgb(cint(R))
End Sub
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 10710848
Ark,

What language you using there?     ;-)

Me.hDC is only in VB6 (and below) and Color.FromArgb(cint(R)) is only in .NET

Idle_Mind
0
 
LVL 17

Expert Comment

by:zzzzzooc
ID: 10712670
>> I couldn't find a way to assign a long value to type color.

I don't know VB.NET so I can't clearly help but Color.FromArgb seems to have arguments for R, G and B so you can try converting the long RGB value to 3 integer values. Hopefully you'll be able to implement the below.

"Convert VB Long Color values to RGB Color values"
http://www.abstractvb.com/code.asp?A=845

Private Sub Command1_Click()
    Dim B As Integer
    Dim G As Integer
    Dim R As Integer
    Dim lngColor As Long

    lngColor = &H800000

    LongToRGB lngColor, R, G, B

    MsgBox "RED=" & R & " GREEN=" & G & " BLUE=" & B
End Sub

Public Sub LongToRGB(ByVal lngColor As Long, intRed As Integer, intGreen As Integer, intBlue As Integer)
    Dim lngColor As Long

    lngColor = lngColor
    intRed = lngColor Mod &H100
    lngColor = lngColor \ &H100
    intGreen = lngColor Mod &H100
    lngColor = lngColor \ &H100
    intBlue = lngColor Mod &H100
End Sub

0
 
LVL 27

Expert Comment

by:Ark
ID: 10718290
Hi Idle_Mind
I used VB6 and actually this string should be
   Me.BackColor = R
I just copied/pasted this string from author's code
0
 

Author Comment

by:8_digits
ID: 10748286
okay fellow humanoids.  I've spent some time on this and basically found out that I'm a moron.  Uh...  You know how I was complaining about converting from long to int?  I don't have to.  Visual Basic.NET uses ints instead of longs and shorts inplace of ints.  Also I can only get the color of a pixel when I actually PAINT something to the form.  It doesn't work with picboxes or buttons or labels or...

Here's your NEW API declarations

    Declare Auto Function getPix Lib "gdi32.dll" Alias "GetPixel"_
 (ByVal dc As Integer, ByVal x As Integer, ByVal y As Integer) As Integer
    Private Declare Function GetDC Lib "user32" (ByVal hwnd As Integer) As Integer
    Private Declare Function ReleaseDC Lib "user32"_
 (ByVal hwnd As Integer, ByVal hdc As Integer) As Integer

notice that nothing uses long.

this is where I call the API functions

    Private Sub Form1_MouseMove _
(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
 Handles MyBase.MouseMove
        Dim intdc As Integer = GetDC(Me.Handle.ToInt32())
        Label1.Text = getPix(intdc, e.X - 4, e.Y - 4).ToString()
        ReleaseDC(Me.Handle.ToInt32(), intdc)

    End Sub

This way only finds the color of the pixel on the empty canvas.  If you move your mouse over a button/label/etc, it will turn to -1 (not colored).  I actually need to find the color of EVERY component on the form.
0
 
LVL 17

Expert Comment

by:zzzzzooc
ID: 10752504
You could just use the desktop's DC (GetDC(0)) as I did in my previous example as all child windows are painted correctly on it. The below example will show how to display the pixel color if the window belongs to your application.. it'll also specify which window (and just added which control.. but most-likely won't be able to be converted to VB.NET). Hopefully you can convert most of it and I've commented most to help with that.


Form1:
=============

Option Explicit

Private Type POINTAPI
    X As Long
    Y As Long
End Type

Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Private Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long

Private lDesktopDC As Long
Private Sub Form_Load()
    'Gets the device context of the desktop
    lDesktopDC = GetDC(0)
    Timer1.Interval = 100
    Timer1.Enabled = True
End Sub
Private Sub Form_Unload(Cancel As Integer)
    Call ReleaseDC(0, lDesktopDC)
End Sub
Private Function GetControlFromHandle(ByVal lHandle As Long) As Object
    Dim objSrch As Object
    For Each objSrch In Me.Controls
        'Instead of On Error I'll hard-code controls to avoid..controls such
        'as Timers won't have window handles = error
        If TypeOf objSrch Is Timer Then
            'Ignore
        Else
            'Found a match!
            If objSrch.hwnd = lHandle Then
                'Set the return of the function to the object we found
                Set GetControlFromHandle = objSrch
                Exit For
            End If
        End If
    Next objSrch
End Function
Private Sub Timer1_Timer()
    Dim tCursorPos As POINTAPI
    Dim lCurrWindow As Long, lThreadID As Long, lProcID As Long
    Dim lRGB As Long
    'Get current x/y position of mouse cursor on screen
    Call GetCursorPos(tCursorPos)
    'Get the handle of the window your mouse is currently hovering over
    lCurrWindow = WindowFromPoint(tCursorPos.X, tCursorPos.Y)
    'Get the Thread ID of the window the mouse cursor is over
    lThreadID = GetWindowThreadProcessId(lCurrWindow, lProcID)
    'If the window's Thread ID matches our app's Thread ID (belongs to the same
    'process)..
    If lThreadID = App.ThreadID Then
        'Get the pixel color and display it
        lRGB = GetPixel(lDesktopDC, tCursorPos.X, tCursorPos.Y)
        Me.BackColor = lRGB
        'For testing purposes.. this is an example of getting the control
        'from handle (doubt it'll work with VB.NET)
        '
        'Check if the handle is the form first..
        If lCurrWindow = Me.hwnd Then
            Me.Caption = Me.Name
        Else
            'If you're in IDE, the IDE will have the same ThreadID as your app
            'so check if the returned object=nothing
            If TypeName(GetControlFromHandle(lCurrWindow)) <> "Nothing" Then
                Me.Caption = GetControlFromHandle(lCurrWindow).Name
            End If
        End If
    End If
End Sub

0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Introduction I needed to skip over some file processing within a For...Next loop in some old production code and wished that VB (classic) had a statement that would drop down to the end of the current iteration, bypassing the statements that were c…
The debugging module of the VB 6 IDE can be accessed by way of the Debug menu item. That menu item can normally be found in the IDE's main menu line as shown in this picture.   There is also a companion Debug Toolbar that looks like the followin…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

24 Experts available now in Live!

Get 1:1 Help Now