Draggable image on transparent window

Just starting out? Need help? Post your questions and find answers here.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

That's not surprising as no window events are being processed in between SetGadgetState commands.
BERESHEIT
Dare
Addict
Addict
Posts: 1965
Joined: Mon May 29, 2006 1:01 am
Location: Outback

Post by Dare »

I suppose it takes a heap of API stuff to make the text background in the image and text box transparent. :?

Code: Select all

ProcedureDLL.l TicksHQ()
  Static maxfreq.q
  Protected t.q
  If maxfreq=0
    QueryPerformanceFrequency_(@maxfreq)
    maxfreq=maxfreq/1000
  EndIf
  QueryPerformanceCounter_(@t)
  ProcedureReturn t/maxfreq
EndProcedure


Structure REGIONDATA
  rdh.RGNDATAHEADER
  buffer.l[100000]
EndStructure

; ===========================================================================================

ProcedureDLL GrabRegion(ImageID, transcolor) ; HBITMAP ImageID, COLORREF transcolor

  ;=======================================================
  ;                                                      =
  ;      Very fast bitmap -> region creator              =
  ;                                                      =
  ;      By netmaestro                                   =
  ;                                                      =
  ;      Contributors: eesau, nico, flype                =
  ;                                                      =
  ;      June 26, 2007                                   =
  ;                                                      =
  ;=======================================================

  Structure RGBTRIPLEC
    rgbtBlue.b
    rgbtGreen.b
    rgbtRed.b
  EndStructure

  GetObject_(ImageID, SizeOf(BITMAP), @bmp.BITMAP)
 
  Protected width       = bmp\bmWidth
  Protected height      = bmp\bmHeight
  Protected hVisibleRgn = CreateRectRgn_(0, 0, width, height)
  Protected tred        = Red(transcolor)
  Protected tgreen      = Green(transcolor)
  Protected tblue       = Blue(transcolor)
 
  BmiInfo.BITMAPINFOHEADER
  With BmiInfo
    \biSize         = SizeOf(BITMAPINFOHEADER)
    \biWidth        = width
    \biHeight       = -height
    \biPlanes       = 1
    \biBitCount     = 24
    \biCompression  = #BI_RGB
  EndWith   
 
  bytesperrow = 4*((3*width+3)/4)

  *ColorBits = AllocateMemory(bytesperrow*height)
  hDC   = GetWindowDC_(#Null)
  iRes  = GetDIBits_(hDC, ImageID, 0, height, *ColorBits, @bmiInfo, #DIB_RGB_COLORS)
  ReleaseDC_(#Null, hDC)
 
  Structure_Max=(width*height*16)+SizeOf(RGNDATAHEADER)
  *Buffer.RGNDATAHEADER=AllocateMemory(Structure_Max)
  *rd.LONG=*Buffer+SizeOf(RGNDATAHEADER)

  bufferloc = 0 : rectcount = 0
  For y=0 To height-1
    pxcount=0
    For x=0 To bytesperrow-1 Step 3
      *px.RGBTRIPLEC = *ColorBits + bytesperrow * y + x
      If *px\rgbtRed&$FF=tred And *px\rgbtGreen&$FF=tgreen And *px\rgbtBlue&$FF=tblue
        transcount = 1 : firsttrans = pxcount
        While *px\rgbtRed&$FF=tred And *px\rgbtGreen&$FF=tgreen And *px\rgbtBlue&$FF=tblue  And x<=bytesperrow-4
          transcount+1 : pxcount+1 : x+3 : *px = *ColorBits + bytesperrow * y + x
        Wend
        rectcount+1
        *rd\l = firsttrans            : *rd+4
        *rd\l = y                     : *rd+4
        *rd\l = firsttrans+transcount : *rd+4
        *rd\l = y+1                   : *rd+4
      EndIf
      pxcount+1
    Next
  Next
 
  With *Buffer
    \dwSize         = SizeOf(RGNDATAHEADER)
    \iType          = #RDH_RECTANGLES
    \nCount         = rectcount
    \nRgnSize       = rectcount * SizeOf(RECT)
    \rcBound\left   = 0
    \rcBound\top    = 0
    \rcBound\right  = width
    \rcBound\bottom = height
  EndWith
 
  RegionSize=SizeOf(RGNDATAHEADER)+(rectcount * SizeOf(RECT))
  hTransparentRgn = ExtCreateRegion_(#Null, RegionSize, *Buffer)
  CombineRgn_(hVisibleRgn, hVisibleRgn, hTransparentRgn, #RGN_XOR)
   
  FreeMemory(*Buffer)
  FreeMemory(*ColorBits)
  DeleteObject_(hTransparentRgn)
 
  ProcedureReturn hVisibleRgn
 
EndProcedure 

Procedure.l counter(ctr)
  StartDrawing(WindowOutput(0))
    DrawText(130,190,"Girl "+Str(ctr),$00FF00)
  StopDrawing()
  SetGadgetText(1,Str(ctr))
  ProcedureReturn ctr+1
EndProcedure

; ===========================================================================================

LoadImage(0, "girl.bmp")

OpenWindow(0,0,0,ImageWidth(0),ImageHeight(0),"", #PB_Window_ScreenCentered|#PB_Window_BorderLess|#PB_Window_Invisible)
CreateGadgetList(WindowID(0))
ImageGadget(0,0,0,0,0,ImageID(0))
TextGadget(1, 130,210,50,20,"")

region = GrabRegion(ImageID(0), #White)

SetWindowRgn_(WindowID(0), region, #True)
HideWindow(0,0)

tm=ElapsedMilliseconds()
Repeat
  WaitWindowEvent(100)
  If ElapsedMilliseconds() > tm + 999
    ctr=counter(ctr)
    tm=ElapsedMilliseconds()
  EndIf
Until GetAsyncKeyState_(#VK_SPACE) & 32768 
Dare2 cut down to size
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

No, sorry to disappoint, but no API required:

Code: Select all

;=========================================================================================== 

ProcedureDLL GrabRegion(ImageID, transcolor) ; HBITMAP ImageID, COLORREF transcolor 

  ;======================================================= 
  ;                                                      = 
  ;      Very fast bitmap -> region creator              = 
  ;                                                      = 
  ;      By netmaestro                                   = 
  ;                                                      = 
  ;      Contributors: eesau, nico, flype                = 
  ;                                                      = 
  ;      June 26, 2007                                   = 
  ;                                                      = 
  ;======================================================= 

  GetObject_(ImageID, SizeOf(BITMAP), @bmp.BITMAP) 
  
  Protected width       = bmp\bmWidth 
  Protected height      = bmp\bmHeight 
  Protected hVisibleRgn = CreateRectRgn_(0, 0, width, height) 
  Protected tred        = Red(transcolor) 
  Protected tgreen      = Green(transcolor) 
  Protected tblue       = Blue(transcolor) 
  
  BmiInfo.BITMAPINFOHEADER 
  With BmiInfo 
    \biSize         = SizeOf(BITMAPINFOHEADER) 
    \biWidth        = width 
    \biHeight       = -height 
    \biPlanes       = 1 
    \biBitCount     = 24 
    \biCompression  = #BI_RGB 
  EndWith    
  
  bytesperrow = 4*((3*width+3)/4) 

  *ColorBits = AllocateMemory(bytesperrow*height) 
  hDC   = GetWindowDC_(#Null) 
  iRes  = GetDIBits_(hDC, ImageID, 0, height, *ColorBits, @bmiInfo, #DIB_RGB_COLORS) 
  ReleaseDC_(#Null, hDC) 
  
  Structure_Max=(width*height*16)+SizeOf(RGNDATAHEADER) 
  *Buffer.RGNDATAHEADER=AllocateMemory(Structure_Max) 
  *rd.LONG=*Buffer+SizeOf(RGNDATAHEADER) 

  bufferloc = 0 : rectcount = 0 
  For y=0 To height-1 
    pxcount=0 
    For x=0 To bytesperrow-1 Step 3 
      *px.RGBTRIPLE = *ColorBits + bytesperrow * y + x 
      If *px\rgbtRed&$FF=tred And *px\rgbtGreen&$FF=tgreen And *px\rgbtBlue&$FF=tblue 
        transcount = 1 : firsttrans = pxcount 
        While *px\rgbtRed&$FF=tred And *px\rgbtGreen&$FF=tgreen And *px\rgbtBlue&$FF=tblue  And x<=bytesperrow-4 
          transcount+1 : pxcount+1 : x+3 : *px = *ColorBits + bytesperrow * y + x 
        Wend 
        rectcount+1 
        *rd\l = firsttrans            : *rd+4 
        *rd\l = y                     : *rd+4 
        *rd\l = firsttrans+transcount : *rd+4 
        *rd\l = y+1                   : *rd+4 
      EndIf 
      pxcount+1 
    Next 
  Next 
  
  With *Buffer 
    \dwSize         = SizeOf(RGNDATAHEADER) 
    \iType          = #RDH_RECTANGLES 
    \nCount         = rectcount 
    \nRgnSize       = rectcount * SizeOf(RECT) 
    \rcBound\left   = 0 
    \rcBound\top    = 0 
    \rcBound\right  = width 
    \rcBound\bottom = height 
  EndWith 
  
  RegionSize=SizeOf(RGNDATAHEADER)+(rectcount * SizeOf(RECT)) 
  hTransparentRgn = ExtCreateRegion_(#Null, RegionSize, *Buffer) 
  CombineRgn_(hVisibleRgn, hVisibleRgn, hTransparentRgn, #RGN_XOR) 
    
  FreeMemory(*Buffer) 
  FreeMemory(*ColorBits) 
  DeleteObject_(hTransparentRgn) 
  
  ProcedureReturn hVisibleRgn 
  
EndProcedure 

Procedure.l counter(ctr) 
  srcdc = StartDrawing(WindowOutput(0)) 
    DrawImage(ImageID(1),130,190)
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawText(130,190,"Girl "+Str(ctr),$00FF00) 
  StopDrawing() 
  ProcedureReturn ctr+1 
EndProcedure 

; =========================================================================================== 

LoadImage(0, "girl.bmp") 

OpenWindow(0,0,0,ImageWidth(0),ImageHeight(0),"", #PB_Window_ScreenCentered|#PB_Window_BorderLess|#PB_Window_Invisible) 
CreateGadgetList(WindowID(0)) 
ImageGadget(0,0,0,0,0,ImageID(0)) 
DisableGadget(0,1)
GrabImage(0,1,130,190,40,20)
region = GrabRegion(ImageID(0), #White) 

SetWindowRgn_(WindowID(0), region, #True) 
HideWindow(0,0) 

tm=ElapsedMilliseconds() 
Repeat 
  WaitWindowEvent(100) 
  If ElapsedMilliseconds() > tm + 999 
    ctr=counter(ctr) 
    tm=ElapsedMilliseconds() 
  EndIf 
Until GetAsyncKeyState_(#VK_SPACE) & 32768 
BERESHEIT
Dare
Addict
Addict
Posts: 1965
Joined: Mon May 29, 2006 1:01 am
Location: Outback

Post by Dare »

netmaestro wrote:No, sorry to disappoint, but no API required:
:lol:

Thanks mate.

And the textgadget ... if you can do that sans api I will eat my ... dinner.


(Was going to say hat but knowing you I thought it too risky - besides, I like my hat)
Dare2 cut down to size
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

No, I think your hat and dinner are safe enough, the textgadget would need a callback trapping WM_CTLCOLORSTATIC and returning a null brush, but even at that you'd have difficulties when the text changed as the null brush doesn't erase anything. It's solved in the drawing-to-windowoutput approach by grabbing the snapshot behind the text ahead of time and drawing first the snapshot and then the transparent text, but it's going to be a pain subclassing the textgadget and doing similar. You're best off contenting yourself with WindowOutput and be done with it.
BERESHEIT
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Just seen ebs' contribution to this drag image thread - another cracker!

Great stuff.
I may look like a mule, but I'm not a complete ass.
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4789
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Post by Fangbeast »

srod I think I've been asking too many questions of professor NetMaestro and taxing his health. Have you shared any food with him lately????

He looks as skinny as you do and I can't detect any humour in his posts so I should leave him alone.

/me falls off the chair, slimes through the corridor into the kitchen and goes to have breakfast.
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4789
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Post by Fangbeast »

In this window, I open the drag and drop window and make an initial call to Counter with a value of 0.

The window works, counter doesn't. Yes, the procedures are declared:):)

Code: Select all

;============================================================================================================================
; Open the drag target window
;============================================================================================================================

Procedure OpenDragBox() 

  If Window_dragbox()
      
    ;SetWindowLong_(WindowID(#Window_dragbox), #GWL_EXSTYLE, GetWindowLong_(WindowID(#Window_dragbox), #GWL_EXSTYLE) | #WS_EX_TOOLWINDOW)
      
    program\dragdrop = 1
  
    AddKeyboardShortcut(#Window_dragbox, #PB_Shortcut_Alt | #PB_Shortcut_D, #Shortcut_dragbox_closedragbox)
  
    GrabImage(#Image_dragbox_dropzone, #Image_dragbox_counter, 0, 0, 60, 25)         ; Create counter image
  
    region = GrabRegion(ImageID(#Image_dragbox_dropzone), #Black)                    ; Create the region for the included picture

    SetWindowRgn_(WindowID(#Window_dragbox), region, #True)                          ; Clip the image to the calculated region
    
    hBrush = CreatePatternBrush_(ImageID(#Image_dragbox_dropzone))                   ; Set the window background to the image.
      
    SetClassLong_(WindowID(#Window_dragbox), #GCL_HBRBACKGROUND, hBrush)             ; Subclass the window to allow dragging around
    
    DrawCounter(50550500)                                                            ; Draw the counter with an initial value of 0
    
    HideWindow(#Window_dragbox, 0)                                                   ; Show the window now that everything is ready
    
    EnableWindowDrop(#Window_dragbox, #PB_Drop_Files, #PB_Drag_Copy)                 ; Enable dragging and dropping on this window
    
    StickyWindow(#Window_dragbox, 1)                                                 ; Make this window stay on top of all others
  
  EndIf

EndProcedure
Just borrowing on everyone's posts in this code and remembering that my drag and drop image is only 80x80, I thought this work work. I was wrong!

Code: Select all

;============================================================================================================================
; Draw the file count on the drop target
;============================================================================================================================

Procedure.l DrawCounter(Counter)

  StartDrawing(WindowOutput(#Window_dragbox))

    DrawImage(ImageID(#Image_dragbox_counter), 20, 20)

    DrawingMode(#PB_2DDrawing_Transparent)

    DrawText(20, 20, Str(Counter) + " Counter me baby")

  StopDrawing()

  ; ProcedureReturn ctr + 1

EndProcedure

I am extremely dumb about graphics and how they work. In 6 years of pb, this is the first time I am touching them. And advertising my lack of knowledge (Ouch!)

EDIT** Had to add in the missing command GrabImage and add the missing image constants (Doh!), that should tell you how little I understand graphics but still no go.
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4789
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Post by Fangbeast »

Okay, I give up. Currently fighting with Vmware converter and that's giving me a headache.
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
vrman3d
User
User
Posts: 13
Joined: Thu Jul 26, 2007 7:44 pm

Possible with OGRE? Trying for colorkeyed transparent win

Post by vrman3d »

Hi Fangbeast, Netmaestro, Dare, Srod and everyone.

This is a great thread, cool stuff, and almost does what I need, HOWEVER:

Is there an easy way to set up things like this with an OGRE3D app? I have tried all sorts of things just to get a bitmap to display as the background of the 3D window to no avail. Perhaps I'm blind, but it seems like there's no way to set an image as a camera background (you can use a color, but not an image).

I'm sure there must be an easy way, since in other languages/sdks it's very common. Any ideas?

I've tried all sorts of things, including using 'Billboards' but that's a kludgy solution, and I need pixel perfect bitmap positioning, not 3d world units, and need the pixel perfect bitmap without texture filtering, etc. And what I'm really looking for is being able to update the 2D bg image on the fly (by drawing to it).

Any help would be greatly appreciated!

Best regards,
-=VRMan=-
Post Reply