Sample pixel value under a transparent window?

Just starting out? Need help? Post your questions and find answers here.
User avatar
Cruster
User
User
Posts: 96
Joined: Fri Jan 23, 2004 12:05 am

Sample pixel value under a transparent window?

Post by Cruster »

Hi all.

I'm struggling with this and am hoping some kind soul might be able to point me in the correct direction.

I'd like to sample pixel values under a transparent window, code below. I think what's happening is I'm instead sampling the value of the transparent window itself, though that may not be the case!

Anyone have any ideas where I'm going wrong and how best I should go about this?

Many thanks in advance.

Code: Select all

;// ----------------------------------------------------------------------------------------------
;             Create a small transparent window and get the pixel value(s) under it 
;// ----------------------------------------------------------------------------------------------

Enumeration
#TransWin
#img
EndEnumeration

;// ----------------------------------------------------------------------------------------------
Procedure TransWin()
;// source: https://www.purebasic.fr/english/viewtopic.php?f=5&t=45362&hilit=+transparent
If OpenWindow(#TransWin, 0, 0, 144, 10, "Grab Window",#PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered)

              SetWindowColor(#TransWin,#Blue)
              SetWindowLong_(WindowID(#TransWin), #GWL_EXSTYLE, #WS_EX_LAYERED | #WS_EX_TOPMOST)
              SetLayeredWindowAttributes_(WindowID(#TransWin),#Blue,0,#LWA_COLORKEY)

EndIf
EndProcedure                            
;// ----------------------------------------------------------------------------------------------              
              
              TransWin()                                            ;// Draw the transparent window
              CreateImage(#img, 144, 10, 32, #PB_Image_Transparent)
              StartDrawing(WindowOutput(#TransWin))
              
                    While (#True)                                   ;// just loop for now
                    Event = WindowEvent()                           ;// Non blocking wait for window event                     
                      If Event = #PB_Event_CloseWindow              ;// window closed ? if yes then exit program
                        Goto exit
                      EndIf
                        Debug  Point(1, 6)                          ;// sample pixel under transparent window at coord 1,6
                                                                    ;// draw a white line in middle of transparent window -
                                                                    ;// - to aid "lining up"
                        For i = 0 To 143 : Plot(i,5,RGB(255,255,255)) : Next      
                    Wend    

              StopDrawing()
                        
;// ----------------------------------------------------------------------------------------------
exit:
              StopDrawing()
              End
              
;// ----------------------------------------------------------------------------------------------
PureBasic 4.3 registered user
infratec
Always Here
Always Here
Posts: 7622
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Sample pixel value under a transparent window?

Post by infratec »

Code: Select all

Procedure HBitmapFromScreen(X, Y, W, H)
  Protected HDC = GetDC_(0)
  Protected HBM = CreateCompatibleBitmap_(HDC, W, H)
  Protected PDC = CreateCompatibleDC_(HDC)
  SelectObject_(PDC, HBM)
  BitBlt_(PDC, 0, 0, W, H, HDC, X, Y, #SRCCOPY)
  DeleteDC_(PDC)
  ReleaseDC_(0, HDC)
  ProcedureReturn HBM
EndProcedure



OpenWindow(0, 0, 0, 400, 200, "Select your area", #PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_ScreenCentered|#PB_Window_Tool)
SetWindowColor(0, #Blue)
SetWindowLong_(WindowID(0), #GWL_EXSTYLE, #WS_EX_LAYERED|#WS_EX_TOPMOST)
SetLayeredWindowAttributes_(WindowID(0), #Blue, 0, #LWA_COLORKEY)

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

x = WindowX(0, #PB_Window_InnerCoordinate)
y = WindowY(0, #PB_Window_InnerCoordinate)
w = WindowWidth(0)
h = WindowHeight(0)

ImageID = HBitmapFromScreen(x, y, w, h)
CloseWindow(0)

OpenWindow(0, 0, 0, w, h, "Selection was ...", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
CanvasGadget(0, 0, 0, w, h)
If StartDrawing(CanvasOutput(0))
  DrawImage(ImageID, 0, 0)
  StopDrawing()
EndIf


Repeat 
  Event = WaitWindowEvent()
  
  Select Event
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 0
          If EventType() = #PB_EventType_LeftClick
            If StartDrawing(CanvasOutput(0))
              Debug RSet(Hex(Point(GetGadgetAttribute(0, #PB_Canvas_MouseX), GetGadgetAttribute(0, #PB_Canvas_MouseY))), 6, "0")
              StopDrawing()
            EndIf
          EndIf
     EndSelect
  EndSelect
Until Event = #PB_Event_CloseWindow
infratec
Always Here
Always Here
Posts: 7622
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Sample pixel value under a transparent window?

Post by infratec »

Or more like that:

Code: Select all

Procedure HBitmapFromScreen(X, Y, W, H)
  Protected HDC = GetDC_(0)
  Protected HBM = CreateCompatibleBitmap_(HDC, W, H)
  Protected PDC = CreateCompatibleDC_(HDC)
  SelectObject_(PDC, HBM)
  BitBlt_(PDC, 0, 0, W, H, HDC, X, Y, #SRCCOPY)
  DeleteDC_(PDC)
  ReleaseDC_(0, HDC)
  ProcedureReturn HBM
EndProcedure



OpenWindow(0, 0, 0, 400, 200, "Select your area", #PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_ScreenCentered|#PB_Window_Tool)
SetWindowColor(0, #Blue)
SetWindowLong_(WindowID(0), #GWL_EXSTYLE, #WS_EX_LAYERED|#WS_EX_TOPMOST)
SetLayeredWindowAttributes_(WindowID(0), #Blue, 0, #LWA_COLORKEY)

CanvasGadget(0, 0, 0, w, h)
HideGadget(0, #True)

PostEvent(#PB_Event_MoveWindow)

Repeat 
  Event = WaitWindowEvent()
  
  Select Event
    Case #WM_LBUTTONDOWN
      If StartDrawing(CanvasOutput(0))
        Debug RSet(Hex(Point(WindowMouseX(0), WindowMouseY(0))), 6, "0")
        StopDrawing()
      EndIf
      
    Case #PB_Event_MoveWindow, #PB_Event_SizeWindow
      x = WindowX(0, #PB_Window_InnerCoordinate)
      y = WindowY(0, #PB_Window_InnerCoordinate)
      w = WindowWidth(0)
      h = WindowHeight(0)
      ImageID = HBitmapFromScreen(x, y, w, h)
      ResizeGadget(0, 0, 0, w, h)
      If StartDrawing(CanvasOutput(0))
        DrawImage(ImageID, 0, 0)
        StopDrawing()
      EndIf
  EndSelect
Until Event = #PB_Event_CloseWindow
But I think it is easier to directly access the pixel via windows API commands.
Then no Gadget and drawing is needed.
infratec
Always Here
Always Here
Posts: 7622
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Sample pixel value under a transparent window?

Post by infratec »

Code: Select all

OpenWindow(0, 0, 0, 400, 200, "Select your area", #PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_ScreenCentered|#PB_Window_Tool)
SetWindowColor(0, #Blue)
SetWindowLong_(WindowID(0), #GWL_EXSTYLE, #WS_EX_LAYERED|#WS_EX_TOPMOST)
SetLayeredWindowAttributes_(WindowID(0), #Blue, 0, #LWA_COLORKEY)

Repeat 
  Event = WaitWindowEvent()
  
  Select Event
    Case #WM_LBUTTONDOWN
      HDC = GetDC_(0)
      Debug RSet(Hex(GetPixel_(HDC, WindowX(0, #PB_Window_InnerCoordinate) + WindowMouseX(0), WindowY(0, #PB_Window_InnerCoordinate) + WindowMouseY(0))), 6, "0")
      ReleaseDC_(0, HDC)
      
  EndSelect
  
Until Event = #PB_Event_CloseWindow
Last edited by infratec on Tue Apr 05, 2022 4:20 pm, edited 1 time in total.
User avatar
Cruster
User
User
Posts: 96
Joined: Fri Jan 23, 2004 12:05 am

Re: Sample pixel value under a transparent window?

Post by Cruster »

Infratec, thank you so much! :D

This -

Code: Select all

OpenWindow(0, 0, 0, 400, 200, "Select your area", #PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_ScreenCentered|#PB_Window_Tool)
SetWindowColor(0, #Blue)
SetWindowLong_(WindowID(0), #GWL_EXSTYLE, #WS_EX_LAYERED|#WS_EX_TOPMOST)
SetLayeredWindowAttributes_(WindowID(0), #Blue, 0, #LWA_COLORKEY)


PostEvent(#PB_Event_MoveWindow)

Repeat 
  Event = WaitWindowEvent()
  
  Select Event
    Case #WM_LBUTTONDOWN
      HDC = GetDC_(0)
      Debug RSet(Hex(GetPixel_(HDC, WindowX(0, #PB_Window_InnerCoordinate) + WindowMouseX(0), WindowY(0, #PB_Window_InnerCoordinate) + WindowMouseY(0))), 6, "0")
      ReleaseDC_(0, HDC)
      
  EndSelect
  
Until Event = #PB_Event_CloseWindow
Is very much what I was after. I won't pretend to understand exactly how it works but it's doing what I was struggling with. It's given me the start I needed to get on with the rest of the code. Thank you! I'm making a screen recorder which will save RGB values along a line (144 pixels long) so that I can then display the recorded patterns on a string of WS2812B LEDs with an Arduino.
PureBasic 4.3 registered user
Post Reply