I have several splash screen animations based on GDImage, working in compositing mode.
unfortunatly none of them written in PureBasic
http://www.objreader.com/index.php?topi ... 37#msg6337
https://depot.webdev.info/resource.awp? ... creen-plus
I am using multi-frame PNG animations, and the key as you did is to use the UpdateLayeredWindow API.
Waiting Screen with transparent background
-
- User
- Posts: 21
- Joined: Sun Aug 10, 2003 11:45 am
- Location: France
- Contact:
Re: Waiting Screen with transparent background
Patrice Terrier
objreader@gmail.com
http://www.objreader.com
Addon: WinLIFT (Skin Engine), GDImage (Graphic library), ObjReader (3D engine)
objreader@gmail.com
http://www.objreader.com
Addon: WinLIFT (Skin Engine), GDImage (Graphic library), ObjReader (3D engine)
Re: Waiting Screen with transparent background
I think there's a bug somewhere in the vectordrawing library:
M.
Code: Select all
Procedure.l SetLayeredWindow(WindowID) ; Mettre l'attribut WS_EX_LAYERED à la fenêtre
SetWindowLong_(WindowID, #GWL_EXSTYLE, GetWindowLong_(WindowID, #GWL_EXSTYLE) | #WS_EX_LAYERED) ; Mettre l'attribut WS_EX_LAYERED à la fenêtre
EndProcedure
Procedure.l AlphaImageWindow(WindowID, ImageID) ; Mettre une image PNG comme fond d'une fenêtre
Protected Image_HDC.i, Image_Bitmap.BITMAP, Image_BitmapInfo.BITMAPINFO, ContextOffset.POINT, Blend.BLENDFUNCTION
Protected Image_Ancienne.i ,xx, yy, x, y, Rouge.l, Vert.l, Bleu.l, AlphaChannel.l
; Précalcul
Protected Dim Echelle.f($FF)
For x = 0 To $FF
Echelle(x) = x / $FF
Next
; Chargement du HDC
Image_HDC = CreateCompatibleDC_(#Null)
Image_Ancienne = SelectObject_(Image_HDC, ImageID)
; Dimension de l'image
GetObject_(ImageID, SizeOf(BITMAP), @Image_Bitmap)
Image_BitmapInfo\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
Image_BitmapInfo\bmiHeader\biWidth = Image_Bitmap\bmWidth
Image_BitmapInfo\bmiHeader\biHeight = Image_Bitmap\bmHeight
Image_BitmapInfo\bmiHeader\biPlanes = 1
Image_BitmapInfo\bmiHeader\biBitCount = 32
; Zone mémoire pour copier l'image
xx = Image_Bitmap\bmWidth - 1
yy = Image_Bitmap\bmHeight - 1
Protected Dim Image.l(xx, yy)
; Copie de l'image en mémoire
GetDIBits_(Image_HDC, ImageID, 0, Image_Bitmap\bmHeight, @Image(), @Image_BitmapInfo, #DIB_RGB_COLORS)
; Modification de l'image en mémoire
For x = 0 To xx
For y = 0 To yy
Couleur = Image(x, y)
AlphaChannel = Couleur >> 24 & $FF
If AlphaChannel < $FF
Rouge = (Couleur & $FF) * Echelle(AlphaChannel)
Vert = (Couleur >> 8 & $FF) * Echelle(AlphaChannel)
Bleu = (Couleur >> 16 & $FF) * Echelle(AlphaChannel)
Image(x, y) = Rouge | Vert << 8 | Bleu << 16 | AlphaChannel << 24
EndIf
Next
Next
; Transfert de la mémoire dans la l'image de base
SetDIBits_(Image_HDC, ImageID, 0, Image_Bitmap\bmHeight, @Image(), @Image_BitmapInfo, #DIB_RGB_COLORS)
; L'image est mise en skin de la fenêtre
Blend\SourceConstantAlpha = 255 ; niveau de transparence
Blend\AlphaFormat = 1 ; Support de la couche alpha
Blend\BlendOp = 0
Blend\BlendFlags = 0
UpdateLayeredWindow_(WindowID, 0, 0, @Image_BitmapInfo + 4, Image_HDC, @ContextOffset, 0, @Blend, 2)
; Fermeture du HDC
SelectObject_(Image_HDC, Image_Ancienne)
DeleteDC_(Image_HDC)
EndProcedure
Procedure Rotate(*oldPos.Point, *RotationCenter.Point, angle.f, *newPos.Point)
Protected xM, yM
angle = angle * #PI / 180
xM = *oldPos\x - *RotationCenter\x
yM = *oldPos\y - *RotationCenter\y
*newPos\x = Round(xM * Cos(angle) + yM * Sin(angle) + *RotationCenter\x, #PB_Round_Nearest)
*newPos\y = Round(- xM * Sin(angle) + yM * Cos(angle) + *RotationCenter\y, #PB_Round_Nearest)
EndProcedure
If OpenWindow(0, 0, 0, 200, 200, "", #PB_Window_BorderLess|#PB_Window_ScreenCentered|#PB_Window_Invisible)
; SetWindowColor(0,$FFFFFF)
SetLayeredWindow(WindowID(0))
Define RotationCenter.Point : RotationCenter\x = 100 : RotationCenter\y = 100
Define startingPos.Point : startingPos\x = 180 : startingPos\y = 100
Define angle.f = 0
Define newpos_red.Point, newpos_green.Point
CreateImage(0, 200, 200, 32, #PB_Image_Transparent)
AddWindowTimer(0, 123, 200)
StartDrawing(ImageOutput(0))
DrawingMode(#PB_2DDrawing_AllChannels)
Box(0, 0, OutputWidth(), OutputHeight(), $00FFFFFF)
StopDrawing()
StartVectorDrawing(ImageVectorOutput(0))
For i = 1 To 8
Rotate(startingPos, RotationCenter, angle, newpos_red)
AddPathCircle(newpos_red\x, newpos_red\y, 10, 0, 360) : VectorSourceColor(RGBA(255, 255, 0, 255)) : FillPath()
If angle = 315 : angle = 0 : Else : angle = angle + 45 : EndIf
Next
StopVectorDrawing()
AlphaImageWindow(WindowID(0), ImageID(0))
StickyWindow(0, 1)
HideWindow(0,0)
Repeat
event = WaitWindowEvent()
If event = #PB_Event_Timer And EventTimer() = 123
; AlphaImageWindow(WindowID(0), ImageID(0)); <=======There is a bug somewhere
EndIf
Until event = #PB_Event_CloseWindow
EndIf
Re: Waiting Screen with transparent background
Different simple test without the transparency :
Is this the right way to do it ? The quality and fluidity is not as good as I thought.
Code: Select all
Enumeration
#Horaire
#AntiHoraire
EndEnumeration
If OpenWindow(0, 0, 0, 200, 200, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 0, 0, 200, 200)
AddWindowTimer(0, 123, 5)
Define rotation = #Horaire
Define start_angle = 0
Define end_angle = 45
Define thickness = 20
Define event
Repeat
event = WaitWindowEvent()
If event = #PB_Event_Gadget And EventGadget() = 0 And EventType() = #PB_EventType_LeftDoubleClick
If rotation = #Horaire : rotation = #AntiHoraire : Else : rotation = #Horaire : EndIf
EndIf
If event = #PB_Event_Timer And EventTimer() = 123
StartVectorDrawing(CanvasVectorOutput(0))
; cleaning
AddPathBox(0, 0, VectorOutputWidth(), VectorOutputHeight())
VectorSourceColor(RGBA(255, 255, 255, 255)) : FillPath()
; background circle
AddPathCircle(100, 100, 80, 0, 360)
VectorSourceColor(RGBA(220, 234, 244, 255))
StrokePath(thickness)
; updated rotating arc
AddPathCircle(100, 100, 80, start_angle, end_angle)
VectorSourceColor(RGBA(148, 178, 228, 255))
StrokePath(thickness)
StopVectorDrawing()
If rotation = #Horaire
start_angle = start_angle + 2
end_angle = end_angle + 2
If start_angle = 360 : start_angle = 0 : end_angle = 45 : EndIf
Else
start_angle = start_angle - 2
end_angle = end_angle - 2
If start_angle = -360 : start_angle = 0 : end_angle = 45 : EndIf
EndIf
EndIf
Until event = #PB_Event_CloseWindow
EndIf
Windows 10 Pro x64
PureBasic 6.20 x64
PureBasic 6.20 x64
Re: Waiting Screen with transparent background
Smoother version (without the WindowTimer) :
Should I use a canvas or an Image ?
Code: Select all
Enumeration
#Horaire
#AntiHoraire
EndEnumeration
If OpenWindow(0, 0, 0, 200, 200, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 0, 0, 200, 200)
; CreateImage(0, 200, 200)
; ImageGadget(1, 0, 0, 200, 200, 0)
Define rotation = #Horaire
Define start_angle = 0
Define end_angle = 45
Define thickness = 20
Define event
Define timer = ElapsedMilliseconds()
Repeat
event = WindowEvent()
If event = #PB_Event_Gadget And EventGadget() = 0 And EventType() = #PB_EventType_LeftDoubleClick
If rotation = #Horaire : rotation = #AntiHoraire : Else : rotation = #Horaire : EndIf
EndIf
If ElapsedMilliseconds() - timer >= 8
timer = ElapsedMilliseconds()
StartVectorDrawing(CanvasVectorOutput(0))
; cleaning
AddPathBox(0, 0, VectorOutputWidth(), VectorOutputHeight())
VectorSourceColor(RGBA(255, 255, 255, 255)) : FillPath()
; background (dark blue)
AddPathCircle(100, 100, 70, 0, 360)
VectorSourceColor(RGBA(184, 204, 237, 255))
FillPath()
; magnifying glass
AddPathCircle(100, 100, 16, 0, 360)
VectorSourceColor(RGBA(255, 255, 255, 255))
StrokePath(6)
MovePathCursor(112, 112)
AddPathLine(128, 128)
StrokePath(6, #PB_Path_RoundEnd)
; background circle (light blue)
AddPathCircle(100, 100, 80, 0, 360)
VectorSourceColor(RGBA(220, 234, 244, 255))
StrokePath(thickness)
; updated rotating arc
AddPathCircle(100, 100, 80, start_angle, end_angle)
VectorSourceColor(RGBA(148, 178, 228, 255))
StrokePath(thickness)
StopVectorDrawing()
; SetGadgetState(1, ImageID(0))
If rotation = #Horaire
start_angle = start_angle + 2
end_angle = end_angle + 2
If start_angle = 360 : start_angle = 0 : end_angle = 45 : EndIf
Else
start_angle = start_angle - 2
end_angle = end_angle - 2
If start_angle = -360 : start_angle = 0 : end_angle = 45 : EndIf
EndIf
EndIf
Delay(1)
Until event = #PB_Event_CloseWindow
EndIf
Windows 10 Pro x64
PureBasic 6.20 x64
PureBasic 6.20 x64
Re: Waiting Screen with transparent background
Yes you're right, you can use also WaitWindowEvent(1) without timer it's the 3rd soluce.
The quality is vector>2d>sprite
The speed is sprite>>>2d>vector
You could try the gif solution, pre compute all frame and just display them.
imagegadget is better for the speed and the transparency, it can be transparent itself.
Canvas is better fot the using of the mouse and is not transparent itself.
M.
The quality is vector>2d>sprite
The speed is sprite>>>2d>vector
You could try the gif solution, pre compute all frame and just display them.
Code: Select all
;
; ------------------------------------------------------------
;
; PureBasic - ImagePlugin GIF Viewer example file
;
; (c) Fantaisie Software
;
; ------------------------------------------------------------
;
; Enable the GIF decoder
UseGIFImageDecoder()
; Loading a GIF file
If LoadImage(0, #PB_Compiler_Home+"Examples/Sources/Data/PureBasicLogo.gif")
OpenWindow(0, 100, 100, DesktopUnscaledX(ImageWidth(0)), DesktopUnscaledY(ImageHeight(0)), "GIF viewer")
CanvasGadget(0, 0, 0, ImageWidth(0), ImageHeight(0))
; Add a timer to animate the GIF, starts immediately to display the first frame witout delay
; AddWindowTimer(0, 0, 1)
; Pre compute all frames here
Repeat
Event = WaitWindowEvent(1)
; Event = WindowEvent()
; If Event = #PB_Event_Timer
SetImageFrame(0, Frame)
; Each GIF frame can have its own delay, so change the timer accordingly
;
;RemoveWindowTimer(0, 0)
;AddWindowTimer(0, 0, GetImageFrameDelay(0))
If StartDrawing(CanvasOutput(0))
DrawImage(ImageID(0), 0, 0)
StopDrawing()
EndIf
; Go to next frame
Frame+1
If Frame >= ImageFrameCount(0) ; Cycle back to first frame, to play in loop
Frame = 0
EndIf
; EndIf
; Delay(1)
Until Event = #PB_Event_CloseWindow
Else
Debug "Impossible to load the file: " + Filename$
EndIf
Canvas is better fot the using of the mouse and is not transparent itself.
M.
Re: Waiting Screen with transparent background
Nice.
You should keep in mind that (at least on windows) the minimum time-out value for timers is 10 ms.
The system has the matter under control, but it's still good to keep that in mind.
You should keep in mind that (at least on windows) the minimum time-out value for timers is 10 ms.
The system has the matter under control, but it's still good to keep that in mind.
MSDN:
If uElapse is less than USER_TIMER_MINIMUM (0x0000000A), the timeout is set to USER_TIMER_MINIMUM. If uElapse is greater than USER_TIMER_MAXIMUM (0x7FFFFFFF), the timeout is set to USER_TIMER_MAXIMUM.
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).