Draggable image on transparent window
- netmaestro
- PureBasic Bullfrog
- Posts: 8451
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
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
- netmaestro
- PureBasic Bullfrog
- Posts: 8451
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
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
- netmaestro
- PureBasic Bullfrog
- Posts: 8451
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
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
- Fangbeast
- PureBasic Protozoa
- Posts: 4789
- Joined: Fri Apr 25, 2003 3:08 pm
- Location: Not Sydney!!! (Bad water, no goats)
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.
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
- Fangbeast
- PureBasic Protozoa
- Posts: 4789
- Joined: Fri Apr 25, 2003 3:08 pm
- Location: Not Sydney!!! (Bad water, no goats)
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:):)
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!
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.
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
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
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
Possible with OGRE? Trying for colorkeyed transparent win
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=-
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=-