To animate text in canvas, you will need to use timer and change the position where text is drawn using Canvas_SetPos.
Petr
UI module: Is there a way to animate a simple "Font" in canvas mode from left to right side ? Any example here at board?, I've found nothing, sorry. If you have a link or a code snippet I am glad to see that! bye, largo
To animate text in canvas, you will need to use timer and change the position where text is drawn using Canvas_SetPos.
Petr
Learn 3D graphics with ThinBASIC, learn TBGL!
Windows 10 64bit - Intel Core i5-3350P @ 3.1GHz - 16 GB RAM - NVIDIA GeForce GTX 1050 Ti 4GB
yes, something like this one? Hi petr, can you check this code example if that's a good way with setting timers (and deleting timers) ? I am wondering in my example why I can't close the dialog (close little application by clicking console "x"), that's not perfect and why I can't break (stop/pause) animation? bye, largo
' Empty GUI script created on 11-25-2011 10:42:26 by largo_winch (ThinAIR) ' Empty GUI script created on 12-19-2011 17:16:56 by largo_winch (ThinAIR) ' Empty GUI script created on 08-06-2012 13:45:12 by largo_winch (ThinAIR) Uses "UI", "console" ' -- ID numbers of controls Begin ControlID %myCanvas %refresh %bClose %tAnimationTimer %timerx %stops %txtbox End ControlID Type BGRA B As Byte G As Byte R As Byte A As Byte End Type Static interrupt As Long ' -- Create dialog here Function TBMain() Local hDlg As Long, mygraf As Long Dialog New 0, "Moving canvas Box_sphere + Font 1a",-1,-1, 300, 240, _ %WS_POPUP Or %WS_VISIBLE Or _ %WS_CLIPCHILDREN Or %WS_CAPTION Or _ %WS_SYSMENU Or %WS_MINIMIZEBOX, 0 To hDlg Dim cx, cy As Long Dialog Pixels hDlg, 300, 300 To Units cx, cy Control Add Canvas, hDlg, %myCanvas, "", 5, 5, cx, cy Control Add Textbox , hDlg, %txtbox, " " ,225 ,210 ,5 ,14 , _ %WS_BORDER Or _ %WS_TABSTOP Or _ %ES_WANTRETURN Control Add Button, hDlg, %refresh, "refresh", 10+cx, 5, 50, 14, Call refreshProc Control Add Button, hDlg, %stops, "stops", 10+cx, 25, 50, 14, Call refreshProc Control Add Button, hDlg, %bClose, "Close", 20, 220, 50, 14, Call bCloseProc Control Handle hDlg,%myCanvas To mygraf Canvas_Attach mygraf, 0 Dialog Show Modal hDlg, Call dlgProc End Function ' -- Callback for dialog ------------- CallBack Function dlgProc() Static myvalue As Long Static indrawing As Long Local mousePosition As POINTAPI Local locX, locY, colrVal As Long Select Case CBMSG Case %WM_INITDIALOG ' -- Put code to be executed after dialog creation here Dialog Set Timer CBHNDL, %tAnimationTimer, 10, %NULL Dialog Set Timer CBHNDL, %timerx, 10, %NULL If InDrawing Then Exit Sub InDrawing = %TRUE Canvas_Attach(CBHNDL, %myCanvas, %TRUE) '%FALSE Canvas_Redraw 'Case %WM_LBUTTONDOWN 'when clicking left mouse button ' -- Get mouse position, convert it to canvas local coordinates 'Control Get Loc CBHNDL, %myCanvas To locX, locY 'Win_GetCursorPos(mousePosition) 'Win_ScreenToClient(CBHNDL, mousePosition) 'mousePosition.x -= locX 'mousePosition.y -= locY 'Control Set Text CBHNDL, %txtbox, Str$(mousePosition.x)+", "+Str$(mousePosition.y) Case %WM_TIMER If CBCTL = %tAnimationTimer Then DrawGraphics(CBHNDL, %myCanvas) Canvas_Redraw End If Case %WM_DESTROY If interrupt <> 1 Then If CBCTL = %stops Then 'Dialog Kill Timer CBHNDL, %tAnimationTimer End If End If Case %WM_CLOSE End Select InDrawing = %FALSE End Function ' -- Callback for close button CallBack Function bCloseProc() If CBMSG = %WM_COMMAND Then If CBCTLMSG = %BN_CLICKED Then ' -- Closes the dialog Dialog End CBHNDL End If End If End Function CallBack Function refreshProc() If CBMSG = %WM_COMMAND Then If CBCTLMSG = %BN_CLICKED Then Dialog Kill Timer CBHNDL, %tAnimationTimer Canvas_Attach(CBHNDL, %myCanvas, %TRUE) DrawGraphics(CBHNDL, %myCanvas) Canvas_Redraw End If End If End Function '----------------------------------------------------------> Sub DrawGraphics(ByVal hWnd As Long, ByVal lCanvas As Long) '----------------------------------------------------------> Local InDrawing As Long Local z, v, r, g, b As Long Local x, y As Double = 20 Local hDlg, mygraf As Long Local oldx, oldy As Double Local d, myExit As Long Local ypush As Double Local t As Single Dim tx As Double, ty As Double r = 228 g = 255 b = 0 v = Rgb(r, g, b) z = (r + g + b)\3 If z < 128 Then z = 255 Else z = 0 z = Rgb(100, 220, 40) Canvas_Clear v Canvas_Color z, v Canvas_Width 1 d = 1 : x = 20 : y = 20 : oldx = x : oldy = y For x = -1 To 175 Step 5.5 '0.1 For ypush = -1 To 175 Step 5.5 ' Canvas_Box(oldx,oldy, oldx+20,oldy+20,0,%GREEN,%GREEN) oldx = x : oldy = y Canvas_Clear %myCanvas Canvas_Clear(Rgb(100,220,0)) Canvas_Box(x,y, x+20,y+20,0,%RED,%GREEN) Canvas_Ellipse(x+50, y+50, x+30, y+30,%GREEN ,%RED, 0 ) Canvas_Color z,v '-- simple font part -------------------------------> Canvas_Font "Comic Sans MS", 18, 0 Canvas_SetPos(10+x/4,80+y/4) Canvas_Print "Canvas Font test: "+Str$(x,y) Canvas_Color(Rgb(255,10,100)) '-- simple font part -------------------------------> Canvas_Redraw Next Next End Sub
Hi,
your code is quite fine - the input issue is caused by fact that when the timer ticks, you do the complete animation inside sub. That is why buttons do not react immediately, as they wait till the animation is complete.
The better approach would be to make single frame of animation on timer tick - that leaves more space "to breathe".
That means mostly omitting the FOR cycles inside DrawGraphics. But how to achieve similar effect without them?
Using static variables. Static variables are special type of local variables, which have one feature extra - they don't get reset between function calls.
So here is the modified version:
PetrUses "UI", "console" ' -- ID numbers of controls Begin ControlID %myCanvas %refresh, %stops %bClose %tAnimationTimer End ControlID ' -- Create dialog here Function TBMain() Local hDlg As Long, mygraf As Long Dialog New 0, "Moving canvas Box_sphere + Font 1a",-1,-1, 300, 240, %WS_POPUP | %WS_VISIBLE | %WS_CLIPCHILDREN | %WS_CAPTION | %WS_SYSMENU | %WS_MINIMIZEBOX, 0 To hDlg Dim cx, cy As Long Dialog Pixels hDlg, 300, 300 To Units cx, cy Control Add Canvas, hDlg, %myCanvas, "", 5, 5, cx, cy Control Add Button, hDlg, %refresh, "refresh", 10+cx, 5, 50, 14, Call refreshProc Control Add Button, hDlg, %stops, "stops", 10+cx, 25, 50, 14, Call stopProc Control Add Button, hDlg, %bClose, "Close", 20, 220, 50, 14, Call bCloseProc Canvas_Attach hDlg,%myCanvas Dialog Show Modal hDlg, Call dlgProc End Function ' -- Callback for dialog ------------- CallBack Function dlgProc() Static myvalue As Long Local mousePosition As POINTAPI Local locX, locY, colrVal As Long Select Case CBMSG Case %WM_INITDIALOG ' -- Put code to be executed after dialog creation here Dialog Set Timer CBHNDL, %tAnimationTimer, 10, %NULL ' -- Attach canvas for double buffer Canvas_Attach(CBHNDL, %myCanvas, %TRUE) '%FALSE Case %WM_TIMER If CBCTL = %tAnimationTimer Then DrawGraphics(CBHNDL, %myCanvas) End If Case %WM_DESTROY Dialog Kill Timer CBHNDL, %tAnimationTimer Case %WM_CLOSE End Select End Function ' -- Callback for close button CallBack Function bCloseProc() If CBMSG = %WM_COMMAND Then If CBCTLMSG = %BN_CLICKED Then ' -- Closes the dialog Dialog End CBHNDL End If End If End Function ' -- Refresh button CallBack Function refreshProc() If CBMSG = %WM_COMMAND Then If CBCTLMSG = %BN_CLICKED Then Dialog Kill Timer CBHNDL, %tAnimationTimer Dialog Set Timer CBHNDL, %tAnimationTimer, 10, %NULL End If End If End Function ' -- Stop button CallBack Function stopProc() If CBMSG = %WM_COMMAND Then If CBCTLMSG = %BN_CLICKED Then Dialog Kill Timer CBHNDL, %tAnimationTimer End If End If End Function '----------------------------------------------------------> Sub DrawGraphics(ByVal hWnd As Long, ByVal lCanvas As Long) '----------------------------------------------------------> Local InDrawing As Long Local z, v, r, g, b As Long Local hDlg, mygraf As Long Local oldx, oldy As Double Local myExit As Long Local t As Single Dim tx As Double, ty As Double ' -- STATICS - they remember their value Static x As Double = -1 Static y As Double = 20 Static yPush As Double r = 228 g = 255 b = 0 v = Rgb(r, g, b) z = (r + g + b)\3 ' -- More elegant than single line IF z = IIf(z < 128, 255, 0) z = Rgb(100, 220, 40) Canvas_Clear v Canvas_Color z, v Canvas_Width 1 oldx = x oldy = y ' -- Imitation of FOR cycles by decomposig step by step x = CYCLE_Next(x, -1, 175, 5.5) If x = -1 Then ypush = CYCLE_Next(ypush, -1, 175, 5.5) End If ' -- End of imitation ' -- Actual drawing S Canvas_Box(oldx,oldy, oldx+20,oldy+20,0,%GREEN,%GREEN) oldx = x : oldy = y Canvas_Clear %myCanvas Canvas_Clear(Rgb(100,220,0)) Canvas_Box(x,y, x+20,y+20,0,%RED,%GREEN) Canvas_Ellipse(x+50, y+50, x+30, y+30,%GREEN ,%RED, 0 ) Canvas_Color z,v '-- simple font part -------------------------------> Canvas_Font "Comic Sans MS", 18, 0 Canvas_SetPos(10+x/4,80+y/4) Canvas_Print "Canvas Font test: "+Str$(x,y) Canvas_Color(Rgb(255,10,100)) '-- simple font part -------------------------------> Canvas_Redraw End Sub
Learn 3D graphics with ThinBASIC, learn TBGL!
Windows 10 64bit - Intel Core i5-3350P @ 3.1GHz - 16 GB RAM - NVIDIA GeForce GTX 1050 Ti 4GB
I don't like only "cycle_next", because I cant understand that function/syntax command. thank you petr for fixing my example
do you know a longer way with "for/next" or "min/max" value (I've tried but without starting font animation) ? If you have another subdrawgraphic solution for me I am very happy about this one
bye, largo
Hi,
Cycle_Next is your friend! For/Next is not good idea to generate the animation, because it blocks the dialog from responding (the subroutine blocks execution until completed).
Cycle_Next works on really simple principle:
- you pass it variable you want to increase
- you pass it minimum value
- you pass it maximum value
- you pass increment
If the increment would return value bigger than maximum, it will return the minimum instead, and than it goes again.
The Cycle_Next(variable, minimum, maximum, step) is just an equivalent for:
variable = variable + step if variable > maximum then variable = minimum ' for step > 0 if variable < minimum then variable = maximum ' for step < 0
Petr
Learn 3D graphics with ThinBASIC, learn TBGL!
Windows 10 64bit - Intel Core i5-3350P @ 3.1GHz - 16 GB RAM - NVIDIA GeForce GTX 1050 Ti 4GB
thank you for explanations and more details. It's always good to understand what's going behind the commands and programmers intention. the idea of cycle_next is good, well done
bye, largo
Last edited by largo_winch; 08-08-2012 at 12:24.
hi petr! It's possible to get some big help for the "circle_next" command to replace it with a usual function as you've mentioned or sub instead of ready "circle_next" command? I tried it but without a good working solution.
bye, largoThe Cycle_Next(variable, minimum, maximum, step) is just an equivalent for:
?
1
2
3variable = variable + step
if variable > maximum then variable = minimum ' for step > 0
if variable < minimum then variable = maximum ' for step < 0
Hi largo_winch!,
I would like to help, but I am not sure I understand your question 100%, could you please give me more info on what do you want to achieve and what is the problem? Does Cycle_Next work not good for you?
Petr
Learn 3D graphics with ThinBASIC, learn TBGL!
Windows 10 64bit - Intel Core i5-3350P @ 3.1GHz - 16 GB RAM - NVIDIA GeForce GTX 1050 Ti 4GB
well, "cycle_next" is working fine here petr. but I wanted to know how I can instead of this command to get a normal function (powerbasic/freebasic, vs, java or something else) with the content of this nice command. I tried to make a function with minimum/maximum and "variable step" in my own function (and delete your "cycle_next" command) but my font animation didn't run. The animatino doesn't work as wished. as programmer I wanted only to achieve what's behind the "cycle_next" as complete function, if that's possible to know
bye, largo
Last edited by largo_winch; 14-01-2013 at 13:45.
Bookmarks