Recent Posts

Pages: [1] 2 3 ... 10
1
The Roundtable / Re: Animation of user interface elements
« Last post by h3kt0r on November 18, 2018, 10:15:19 PM »
Great samples, thank you for sharing this !
2
General Questions / Re: Editor issues
« Last post by ckoehn on November 18, 2018, 11:47:59 AM »
The About says I have:
IWBASIC IDE 3.05
Compiler ver 2.095

I think I found the problem with my program, although it puzzles me.  I put an XBEE on my sons computer with his emulator running, and set up my program with an XBEE.  It's been running since 9:22:08 Saturday morning.  That would mean that com0com was messing up.  The puzzling part is I have com0com running on a customers computer 24/7 acting as a pipe.  Data coming in on a real comport with a listening program processing data and passing it through on a virtual port, and his main program reading data from the other side of the virtual port with everything running constantly and it works.

I guess live and learn.

Later,
Clint
3
The Roundtable / Re: Animation of user interface elements
« Last post by fasecero on November 18, 2018, 09:01:07 AM »
Brian, thanks. Yes, the sample was composed just for the 4 animations, not for the images. For the left side to handle an indeterminate number of images it would require to be completely rewritten. I'll take a look but after some time. Thanks for trying in out! These new techs opens a new door to animated ownerdraw controls, custom animated windows frames, etc.
4
The Roundtable / Re: Animation of user interface elements
« Last post by Brian Pugh on November 18, 2018, 05:20:52 AM »
Fasecero,

Just been trying the jpeg viewer - very impressive! I was trying it with some of my own pics, and it didn't see them. I changed their extension from jpg to jpeg, and increased the number in the j loop, but no banana. Is it designed to only show four items. Can it show more than four items?

But great work - I loved it

Brian
5
Tutorials / Understanding constants and messages
« Last post by Andy on November 18, 2018, 04:23:48 AM »
For the longest time I was totally confused over messages in windows programming, so hopefully this will help any one learning about them.

Constants:

A constant will be given a name plus a value assigned to it – this value does not change, it remains “constant”, hence the name constant.

CONST MyWidgit = 10

MyWigit is a constant I made up just now, and gave it a value of 10.

Now MS have thousands of constants that they have named, and each has a value they have assigned to them.

So now we have this in mind, I will move on the messages.

Messages:

What is a message in programming, and what does it have to do with constants?

All controls we make in a window (button, edit box, static etc) are all windows in their own right, and the “parent” window is the window they appear in.

These “controls” are able to accept “messages” from a program you write – but also, they can “send a message” to your program with some information.

We use the SendMessage command to do any of these two functions.

So lets take an example

(Example 1):

SENDMESSAGE win,LVM_DeleteAllItems,0,0,ListView

And break it down….

“win” is the parent window in our program

“LVM_DeleteAllItems” is a name of a constant that will tell the control what we want it to do – in this case delete all items out of a list view.

0,0, we will ignore just for now.

ListView is the name of our list view control in our program.

So we are sending a message to our list view control to delete all its items, and the list view belongs to the window “win”.

Now what about those other paramers 0,0?

These two parameters are used to send extra “information / instructions” to the control if we need to, in the above example they are not needed hence we leave them zero.

These parameters are called Wparam & Lparam – it is not important to know why they are named like that, just that at times we will need them.


(Example 2):

Getting information from a control.

TextLength = SendMessage(win,WM_GETTEXTLENGTH,0,0,EditBox)

With the same window “win” we want to get the length of text that is in an edit box (here called “EditBox”) control, so here we can use the constant “WM_GETTEXTLENGTH”.

The variable TextLength will hold the value (the number of characters that are typed in the edit box), which could be 0,1,2… 58 etc.

How on earth do I know what constant to use?

This is what has confused me for such a long time, and this is how I do it…..

If we take example 2, I knew I wanted to find out how many characters were in an edit box, so logically it must have something to do with “text”, “characters”, “length” etc.

Before I wrote the constants search program (link at the bottom), I would search the Internet for something like “number of characters in an edit box”, but that didn’t really help.

I was told of “msdn” which is MS’s main site for programming development.

Adding “msdn” onto the search got me closer, but still really didn’t find anything.

This is why I wrote the constants search program, it makes life so much easier.

In the program if I search for “text” and “All control types” it does appear in a list of 96 search results.

If I search “length” and “All control types” it shows just 9 results, either way you come up with WM_GETTEXTLENGTH in both.

When you read its description:

“An application sends a WM_GETTEXTLENGTH message to determine the length, in characters, of the text associated with a window” – here a window for us means the edit box control – we know that’s the one to use.

Finally, if we search the Internet like this “WM_GETTEXTLENGTH msdn” we get exactly what we are searching for – the answer.

msdn describes what it does, and tells you what those Wparam and Lparam values should be, here zero in both cases.

Constants search program:
https://www.ionicwind.com/forums/index.php?topic=6245.msg45848;topicseen#msg45848

Phew.

Hope this is clearer than mud!

Andy.
6
Shared INC's and LIB's / Re: Constants search Version 5 - here.
« Last post by Andy on November 18, 2018, 02:43:42 AM »
Other functions of the program (Version 5 above).

You can use Ctrl + T to toggle between viewing constants and set id's which are added to the builder section.

You can simply press the <Enter> key to add a constant to the builder, as well as double clicking, and of course the "Add to builder" button.

Above the number of controls listed text is another text that tell you which option was used to populate the list view, i.e. an option 1 search, or option 2 search for word or value.

Hiding the main window when selecting a file to save the list view has now been removed - it's not needed.

If you add a constant to the builder, the "Send list to file" button is disabled, or if the builder is empty, it is enabled - after all you either want to do one thing or the other.

Every little help!

Andy.
7
The Roundtable / Re: Animation of user interface elements: Part 3 (Direct2D)
« Last post by fasecero on November 17, 2018, 08:49:22 PM »
This final example combines Windows Animation Manager + Direct2D. These two combined can achieve impressive results. This example still needs a few readjustments, for instance adjusting the layout after resizing the window. I'm excited about the idea of using these technologies in CUSTOMDRAW / OWNERDRAW controls, so I have something to play with.

Note: for this example to work you need to unzip the content of the resources.zip file below in the dll folder location. It has some images and one aditional .gif file inside.

Code: [Select]

$INCLUDE "animation.inc"

SETPRECISION 0

' animation variables
pointer storyboard1 = 0 ' movement to big
pointer storyboard2 = 0 ' movement to small
pointer movement[6, 5] ' animated variables
' direct2d variables
pointer render = 0
pointer brush ' brush handle
pointer images[6] ' bitmap handles
pointer textformat ' D2D font equivalent
' location variables
WINRECT area[6] ' image rectange fixed areas
WINRECT animArea[6] ' image rectange animated areas
INT position[6] ' image order inside rectangles
WINRECT textarea
' gif
INT TIMER_1 = 1
pointer gifhandle = 0
INT gifWidth = 0
INT gifHeight = 0
' other
INT posClick
pointer temp, temp2, temp3 ' helper pointer for arrays
INT j, k

' window
WINDOW w1
OPENWINDOW w1,0,0,1000,600,@MINBOX|@MAXBOX|@SIZE|@NOAUTODRAW|@HIDDEN,NULL,"Direct2D sample",&w1_handler
OnInit()
SHOWWINDOW w1, @SWMAXIMIZED
CreateAnimationVariables()

' main loop
WAITUNTIL w1 = 0
END

' window procedure
SUB w1_handler(), INT
SELECT @MESSAGE
CASE @IDCREATE
CENTERWINDOW w1

CASE @IDCLOSEWINDOW
OnClose()
CLOSEWINDOW w1

CASE @IDLBUTTONDN
OnMouseClick()

CASE @IDPAINT
OnPaint()

CASE @IDSIZE
OnSize()

CASE @IDTIMER
SELECT @WPARAM
CASE TIMER_1
gifOnTimer(w1.hwnd, gifhandle, TIMER_1)
ENDSELECT
ENDSELECT

RETURN 0
ENDSUB

' -------------------------------------------------------------------------------------------------------------------
' EVENTS
' -------------------------------------------------------------------------------------------------------------------

SUB OnInit()
CoInitialize(0)

' init animation library
HRESULT hr = UIAnimationInit(&OnAnimationTick)
IF hr > 0 THEN
_MessageBox(0, "The initialization has failed with code: " + STR$(hr), " Windows Animation Manager", 0)
_SendMessage(w1.hwnd, WM_CLOSE, 0, 0)
RETURN
ENDIF

' init direct2d library
hr = D2DInit()
IF hr > 0 THEN
_MessageBox(0, "The initialization has failed with code: " + STR$(hr), "Direct2D", 0)
_SendMessage(w1.hwnd, WM_CLOSE, 0, 0)
RETURN
ENDIF

' create the direct2d render target
WINRECT rc
GetClientRect(w1.hwnd, rc)
render = D2DRenderTargetCreate(w1.hwnd, rc.right, rc.bottom)

' create a solid brush
brush = D2DSolidBrushCreate(render, 0, 0, 0, 255)

' initial areas
CalculateAreas(rc)

' initial values
FOR j = 1 TO 5
position[j] = j
NEXT j

' load bitmap handles
FOR j = 1 TO 5
iwstring fullpath[MAX_PATH] = GETSTARTPATHW + L"image" + WSTR$(j) + L".jpeg"
temp = D2DBitmapLoadFromFile(render, &fullpath, 0, 0)
images[j] = temp + 0
NEXT j

' create a font
textformat = D2DTextFormatCreate(render, L"SegoeUI", 20.0, DWRITE_FONT_WEIGHT_REGULAR, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, DWRITE_TEXT_ALIGNMENT_LEADING, DWRITE_PARAGRAPH_ALIGNMENT_CENTER)

' load gif
gifhandle = gifAttach(w1.hwnd, TIMER_1, S2W(getstartpath + "folder.gif"), render)
GifGetSize(gifhandle, gifWidth, gifHeight)
ENDSUB

SUB OnClose()
' delete gif
gifDetach(w1.hwnd, gifhandle)

' delete brush
D2DSolidBrushRelease(brush)

' delete the font
D2DTextFormatRelease(textformat)

' delete bitmap handles
FOR j = 1 TO 5
temp = images[j] + 0
D2DBitmapRelease(temp)
NEXT j

' destroy direct2d render target
D2DRenderTargetDestroy(render)

' finish direct2d library
D2DFinish()

' delete animmation variables
FOR j = 1 TO 5
FOR k = 1 TO 4
temp = movement[j, k] + 0
UIAnimationVariableRemove(temp)
NEXT k
NEXT j

' delete the storyboard if still exists
IF storyboard1 THEN UIAnimationStoryboardRemove(storyboard1)
IF storyboard2 THEN UIAnimationStoryboardRemove(storyboard2)

' finish the animation library
UIAnimationFinish()

CoUninitialize()
ENDSUB

SUB OnPaint()
Paint()
ENDSUB

SUB OnSize()
UpdateSize()
ENDSUB

SUB OnMouseClick()
IF UIAnimationStoryboardIsPlaying(storyboard1) = 1 OR UIAnimationStoryboardIsPlaying(storyboard2) = 1 THEN RETURN

posClick = 0

POINT p
GetCursorPos(&p)
ScreenToClient(w1.hwnd, &p)

FOR j = 1 TO 4
IF area[j].left <= p.x AND area[j].right >= p.x THEN
IF area[j].top <= p.y AND area[j].bottom >= p.y THEN
posClick = j
ENDIF
ENDIF
NEXT j

IF posClick THEN
' switch places
INT p1 = position[5]
INT p2 = position[posClick]
position[5] = p2
position[posClick] = p1

' make the animation
AnimateImages()
ENDIF
ENDSUB

' -------------------------------------------------------------------------------------------------------------------
' LOCATION ROUTINES
' -------------------------------------------------------------------------------------------------------------------

SUB CalculateAreas(WINRECT rc)
' based on client area size calculate image's position
INT d = 16
INT tx = 120
INT ty = 60

INT sy = (rc.bottom - 6 * d - ty) / 4.0
INT by = rc.bottom - 2 * d

INT sx = 1.2 * sy

INT dx = sx
IF tx > sx THEN dx = tx

INT bx = rc.right - 3 * d - dx

' small rectangles
FOR j = 1 TO 4
area[j].left  = d
area[j].right = area[j].left + sx
area[j].top = d * (j) + sy * (j - 1)
area[j].bottom = area[j].top + sy - 20
NEXT j

' big rectangle
area[5].left  = d + dx + d
area[5].right = rc.right - d
area[5].top = d
area[5].bottom = rc.bottom - d

FOR j = 1 TO 5
INT current = position[j]
animArea[current] = area[j]
NEXT j

' text rectangle
textarea.left = d
textarea.top  = 5 * d + 4 * sy
textarea.right = textarea.left + tx
textarea.bottom = textarea.top + ty
ENDSUB

' -------------------------------------------------------------------------------------------------------------------
' DIRECT2D ROUTINES
' -------------------------------------------------------------------------------------------------------------------

SUB Paint()
IF render THEN
D2DRenderBegin(render)
D2DFillSolidColor(render, 255, 255, 255,  255)

' render gif
RenderGif(gifhandle, textarea.left + 80, textarea.top - 30, textarea.left + 80 + gifWidth, textarea.top - 30 + gifHeight)

FOR j = 1 to 5
'INT d = -1
'D2DRenderOutline(render, brush, area[j].left - d, area[j].top - d, area[j].right + d, area[j].bottom + d)
NEXT j

FOR j = 1 to 5
temp = images[j] + 0
D2DRenderBitmap(render, temp, animArea[j].left, animArea[j].top, animArea[j].right, animArea[j].bottom, 255)
NEXT j

' render text
D2DRenderText(render, brush, L"Select an image", textarea.left, textarea.top, textarea.right, textarea.bottom, textformat)

' if anything doesn't work this is a good spot to check what's going on
HRESULT hr = D2DRenderEnd(render)   ' in case of error 'hr' will have the error code
'_MessageBox(0, STR$(hr), "render error", 0)
ENDIF
ENDSUB

SUB UpdateSize()
IF UIAnimationStoryboardIsPlaying(storyboard1) = 1 OR UIAnimationStoryboardIsPlaying(storyboard2) = 1 THEN RETURN

WINRECT rc
GetClientRect(w1.hwnd, rc)
D2DRenderTargetResize(render, rc.right, rc.bottom) ' update render target area
CalculateAreas(rc)
InvalidateRect(w1.hwnd, NULL, NULL)
ENDSUB

' -------------------------------------------------------------------------------------------------------------------
' ANIMATION ROUTINES
' -------------------------------------------------------------------------------------------------------------------

SUB CreateAnimationVariables()
FOR j = 1 TO 5
FOR k = 1 TO 4
SELECT k
CASE 1 : temp = UIAnimationVariableAdd(area[j].left, 0, 32000)
CASE 2 : temp = UIAnimationVariableAdd(area[j].top, 0, 32000)
CASE 3 : temp = UIAnimationVariableAdd(area[j].right, 0, 32000)
CASE 4 : temp = UIAnimationVariableAdd(area[j].bottom, 0, 32000)
ENDSELECT

movement[j, k] = temp + 0
NEXT k
NEXT j
ENDSUB

SUB AnimateImages() ' this function encapsulates the whole animation info
' create storyboards
storyboard1 = UIAnimationStoryBoardAdd(storyboard1) ' movement to big
storyboard2 = UIAnimationStoryBoardAdd(storyboard2) ' movement to small

IF storyboard1 <> 0 AND storyboard2 <> 0 THEN
' create one transition per variable
pointer transition[3, 5]
float duration = 0.7
INT current_area = 0
INT current_var = 0

FOR j = 1 TO 2
IF j = 1 THEN current_area = 5 ELSE current_area = posClick
IF j = 1 THEN current_var = position[5] ELSE current_var = position[posClick]

FOR k = 1 TO 4
SELECT k
CASE 1 : temp = UIAnimationTransitionAccDecAdd(duration, area[current_area].left, 0.5, 0.5) ' duration, final value, acc ratio, dec ratio
CASE 2 : temp = UIAnimationTransitionAccDecAdd(duration, area[current_area].top, 0.5, 0.5)
CASE 3 : temp = UIAnimationTransitionAccDecAdd(duration, area[current_area].right, 0.5, 0.5)
CASE 4 : temp = UIAnimationTransitionAccDecAdd(duration, area[current_area].bottom, 0.5, 0.5)
ENDSELECT

transition[j, k] = temp + 0

' comunicate the transition with its variable
temp2 = movement[current_var, k] + 0

IF j = 1 THEN
UIAnimationStoryBoardTransitionJoin(storyboard1, temp, temp2)
ELSE
UIAnimationStoryBoardTransitionJoin(storyboard2, temp, temp2)
ENDIF
NEXT k
NEXT j

' play the animation
UIAnimationStoryboardPlay(storyboard1)
UIAnimationStoryboardPlay(storyboard2)

' delete the transitions (no need to wait till the animation finish)
FOR j = 1 TO 2
FOR k = 1 TO 4
temp3 = transition[j, k] + 0
UIAnimationTransitionRemove(temp3)
NEXT k
NEXT j
ENDIF
ENDSUB

SUB OnAnimationTick() ' this function is called every time any animation needs an update
IF UIAnimationStoryboardIsPlaying(storyboard1) = 1 OR UIAnimationStoryboardIsPlaying(storyboard2) = 1 THEN

FOR j = 1 TO 2
IF j = 1 THEN current_area = 5 ELSE current_area = posClick
IF j = 1 THEN current_var = position[5] ELSE current_var = position[posClick]

FOR k = 1 TO 4
temp2 = movement[current_var, k] + 0
INT value = UIAnimationVariableGetCurrentValue(temp2)

SELECT k
CASE 1 : animArea[current_var].left = value
CASE 2 : animArea[current_var].top = value
CASE 3 : animArea[current_var].right = value
CASE 4 : animArea[current_var].bottom = value
ENDSELECT
NEXT k
NEXT j

' update the window, this will call @IDPAINT
InvalidateRect(w1.hwnd, NULL, NULL)
ENDIF
ENDSUB

I have also expanded the Media Fundation example based on Brian's sugestions as well. Now it shows the elapsed time and the remaining time. It shows a progress bar while the video is displayed and you can seek the video position clicking over the progress bar. For this example to work, you have to download the library again (on my first post) and import the dll again as well since I had to add two new functions.

Code: [Select]
$INCLUDE "windowssdk.inc"
$INCLUDE "shlwapi.inc"
$INCLUDE "animation.inc"

$USE "animation.lib"

' direct2d variables
pointer render1 = 0
pointer render2 = 0
pointer blackbrush1, blackbrush2
pointer greenbrush1
pointer whitebrush1, whitebrush2
pointer textformat1, textformat2
' media fundation
CONST TIMER_1 = 1
pointer mfdata = 0
INT paused = FALSE
UINT64 duration ' video file duration in 100-nanosecond units
' other
INT overlayHeight = 40
INT progHeight = 3
INT show_overlay = 1
string name
' window
WINDOW w1, w2
OPENWINDOW w1,0,0,600,400,@MINBOX|@MAXBOX|@SIZE|@NOAUTODRAW|@HIDDEN,NULL,"Media Fundation Demo",&w1_handler
OPENWINDOW w2,0,0,600,300,@NOCAPTION|@NOAUTODRAW,w1, "", &w2_handler
OnInit()
SHOWWINDOW w1, @SWSHOW

' main loop
WAITUNTIL w1 = 0
END

' -------------------------------------------------------------------------------------------------------------------
' WINDOW PROCEDURES
' -------------------------------------------------------------------------------------------------------------------

SUB w2_handler(), INT
SELECT @MESSAGE
CASE @IDPAINT
OnPaint2()

CASE @IDSIZE
OnSize2()

CASE @IDCLOSEWINDOW
CLOSEWINDOW w2

CASE @IDKEYUP
OnKeyboard()
ENDSELECT

RETURN 0
ENDSUB

SUB w1_handler(), INT
SELECT @MESSAGE
CASE @IDCREATE
CENTERWINDOW w1

CASE @IDCLOSEWINDOW
OnClose()
CLOSEWINDOW w1

CASE @IDPAINT
OnPaint1()

CASE @IDSIZE
OnSize1()

CASE @IDLBUTTONDN
OnMouseClick()

CASE @IDKEYUP
OnKeyboard()

CASE @IDTIMER
SELECT @WPARAM
CASE TIMER_1
InvalidateRect(w1.hwnd, NULL, NULL)
ENDSELECT
ENDSELECT

RETURN 0
ENDSUB

' -------------------------------------------------------------------------------------------------------------------
' EVENTS
' -------------------------------------------------------------------------------------------------------------------

SUB OnInit()
CoInitialize(0)

' init direct2d library
HRESULT hr = D2DInit()
IF hr > 0 THEN
_MessageBox(0, "The initialization has failed with code: " + STR$(hr), "Direct2D", 0)
_SendMessage(w1.hwnd, WM_CLOSE, 0, 0)
RETURN
ENDIF

' create the direct2d render target
WINRECT rc
GetClientRect(w1.hwnd, rc)
render1 = D2DRenderTargetCreate(w1.hwnd, rc.right, rc.bottom)
GetClientRect(w2.hwnd, rc)
render2 = D2DRenderTargetCreate(w2.hwnd, rc.right, rc.bottom)

' create a solid brush
blackbrush1 = D2DSolidBrushCreate(render1, 0, 0, 0, 255)
blackbrush2 = D2DSolidBrushCreate(render2, 0, 0, 0, 255)
greenbrush1 = D2DSolidBrushCreate(render1, 0, 150, 0, 255)
whitebrush1 = D2DSolidBrushCreate(render1, 255, 255, 255, 255)
whitebrush2 = D2DSolidBrushCreate(render2, 255, 255, 255, 255)

' create fonts
textformat1 = D2DTextFormatCreate(render1, L"SegoeUI", 15.0, DWRITE_FONT_WEIGHT_REGULAR, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, DWRITE_TEXT_ALIGNMENT_LEADING, DWRITE_PARAGRAPH_ALIGNMENT_CENTER)
textformat2 = D2DTextFormatCreate(render2, L"SegoeUI", 20.0, DWRITE_FONT_WEIGHT_REGULAR, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, DWRITE_TEXT_ALIGNMENT_CENTER, DWRITE_PARAGRAPH_ALIGNMENT_CENTER)

ENDSUB

SUB OnClose()
' delete the fonts
D2DTextFormatRelease(textformat1)
D2DTextFormatRelease(textformat2)

' delete brush
D2DSolidBrushRelease(blackbrush1)
D2DSolidBrushRelease(blackbrush2)
D2DSolidBrushRelease(greenbrush1)
D2DSolidBrushRelease(whitebrush1)
D2DSolidBrushRelease(whitebrush2)

' destroy direct2d render target
D2DRenderTargetDestroy(render1)
D2DRenderTargetDestroy(render2)

' finish direct2d library
D2DFinish()

MFVideoShutdown(mfdata)
CoUninitialize()
ENDSUB

' -------------------------------------------------------------------------------------------------------------------
' KEYBOARD & MOUSE EVENTS
' -------------------------------------------------------------------------------------------------------------------

SUB OnMouseClick()
IF mfdata THEN
WINRECT rc
GetClientRect(w1.hwnd, rc)

POINT p
GetCursorPos(&p)
ScreenToClient(w1.hwnd, &p)

UINT64 width = rc.right
UINT64 mx = p.x
UINT64 pos = (mx/FLT(width)) * duration

MFVideoSetPosition(mfdata, pos)
ENDIF
ENDSUB

SUB OnKeyboard()
SELECT @WPARAM
CASE 32 ' spacebar
paused = NOT(paused)

IF paused THEN
MFVideoPause(mfdata)
ELSE
MFVideoPlay(mfdata)
ENDIF
CASE 79 ' O letter
OpenVideo()
CASE 27 ' escape key
'
CASE 17 ' control key
INT value = show_overlay
IF value THEN show_overlay = 0 ELSE show_overlay = 1
OnSize1()
ENDSELECT
ENDSUB

' -------------------------------------------------------------------------------------------------------------------
' MEDIA FUNDATION ROUTINES
' -------------------------------------------------------------------------------------------------------------------

DECLARE CDECL EXTERN sprintf(POINTER p, POINTER p, ...), INT

SUB FormatTime(UINT64 _time, INT offset), string
string time = ""
UINT64 t = _time / 10000000 ' duration in seconds
INT h = floor(t/3600)
int m = (t/60)%60
int s = t%60 + offset
sprintf(time, "%02d:%02d:%02d", h, m, s)
RETURN time
ENDSUB

SUB OpenVideo()
ISTRING filename[MAX_PATH]
STRING filter = "All Files (*.*)|*.*|MP4 Videos (*.mp4)|*.mp4||"

filename = FILEREQUEST("Select video file",0,1,filter,"mp4",0, "C:\\")

IF LEN(filename) THEN
MFVideoShutdown(mfdata)
mfdata = MFVideoInit(w2.hwnd)
STOPTIMER w1, 1000
duration = MFVideoLoadFromFile(mfdata, S2W(filename))

MFVideoPlay(mfdata)
MFVideoLoop(mfdata, TRUE)
OnSize1()
OnSize2()
InvalidateRect(w1.hwnd, NULL, true)
InvalidateRect(w2.hwnd, NULL, true)

pointer p = PathFindFileName(&filename)
name = *<string>p

STARTTIMER w1, 33, TIMER_1
ENDIF
ENDSUB

' -------------------------------------------------------------------------------------------------------------------
' SIZE ROUTINES
' -------------------------------------------------------------------------------------------------------------------

SUB OnSize1()
WINRECT rc
GetClientRect(w1.hwnd, rc)
D2DRenderTargetResize(render1, rc.right, rc.bottom) ' update render target area

INT height = 0
if show_overlay THEN height = overlayHeight

SETSIZE w2, 0, 0, rc.right, rc.bottom - height
ENDSUB

SUB OnSize2()
WINRECT rc
GetClientRect(w2.hwnd, rc)
D2DRenderTargetResize(render2, rc.right, rc.bottom) ' update render target area
ENDSUB

' -------------------------------------------------------------------------------------------------------------------
' PAINT ROUTINES
' -------------------------------------------------------------------------------------------------------------------

SUB OnPaint1()
INT width, height

IF render1 THEN
D2DRenderBegin(render1)
D2DRenderGetSize(render1, width, height)

IF mfdata = 0 THEN
D2DFillSolidColor(render1, 0, 0, 0, 255)
ELSE
' draw the overlay background
D2DRenderRectangle(render1, blackbrush1, 0, height - overlayHeight, width, height)

' calculate progress_width
UINT64 pos = MFVideoGetPosition(mfdata)
UINT64 progress_width = (pos/FLT(duration)) * width
D2DRenderRectangle(render1, greenbrush1, 0, height - progHeight- 1, progress_width, height - 1)

INT rem_width = 60

' draw elapsed time
wstring timeElapsed = S2W(FormatTime(pos, 1))
D2DRenderText(render1, whitebrush1, timeElapsed + L"      " + s2w(name), 10, height - overlayHeight, width - 10 - rem_width - 20, height, textformat1)
' draw remaining time
wstring timeRemaining = S2W("-" + FormatTime(duration - pos, 1))
D2DRenderText(render1, whitebrush1, timeRemaining, width - 10 - rem_width, height - overlayHeight, width - 10, height, textformat1)
ENDIF

' if anything doesn't work this is a good spot to check what's going on
HRESULT hr = D2DRenderEnd(render1)   ' in case of error 'hr' will have the error code
'_MessageBox(0, STR$(hr), "render error", 0)
ENDIF
ENDSUB

SUB OnPaint2()
INT width, height

IF mfdata THEN
MFVideoRefresh(mfdata)
ELSE
IF render2 THEN
D2DRenderBegin(render2)
D2DRenderGetSize(render2, width, height)
D2DFillSolidColor(render2, 0, 0, 0, 255)

' render text
wstring text = L"Press 'O' to open a video file" + WCHR$(10) + L"Press 'SPACEBAR' to pause/resume video" _
+ WCHR$(10) + L"Press 'CONTROL' to show/hide progress"
D2DRenderText(render2, whitebrush2, text, 0, 0, width, height, textformat2)

' if anything doesn't work this is a good spot to check what's going on
HRESULT hr = D2DRenderEnd(render2)   ' in case of error 'hr' will have the error code
'_MessageBox(0, STR$(hr), "render error", 0)
ENDIF
ENDIF
ENDSUB

This is pretty much it! Have fun!
8
The Roundtable / Re: Animation of user interface elements: Part 2 (Animation Manager)
« Last post by fasecero on November 17, 2018, 08:41:18 PM »
Windows Animation Manager is a mechanism to make any kind of animations. You can drop Direct2D and use gdi, or gdiplus, or a game engine. These sets of functions can help to achieve complex animations regardless the render engine. The sample fades the window's background to a new randomly-generated color every time you click over the window client area. It's just an excuse to demostrate how it works.

Code: [Select]

$INCLUDE "animation.inc"

' animation variables
pointer storyboard = 0 ' always initialize a storyboard with a zero
pointer redvar, greenvar, bluevar ' animation variables
' direct2d variables
pointer render

INT red, green, blue

' window
WINDOW w1
OPENWINDOW w1,0,0,600,400,@MINBOX|@MAXBOX|@SIZE|@NOAUTODRAW,NULL,"Click to animate the background color",&w1_handler
SETFONT w1, "Segoe UI", 9, 400
OnInit()

' main loop
WAITUNTIL w1 = 0
END
 
' window procedure
SUB w1_handler(), INT
SELECT @MESSAGE
CASE @IDCREATE
CENTERWINDOW w1

CASE @IDCLOSEWINDOW
OnClose()
CLOSEWINDOW w1

CASE @IDLBUTTONDN
' change and animate the background color
AnimateBackroundColor(GetRandomNumber(0, 255), GetRandomNumber(0, 255), GetRandomNumber(0, 255))

CASE @IDPAINT
OnPaint()

CASE @IDSIZE
OnSize()
ENDSELECT

RETURN 0
ENDSUB

' -------------------------------------------------------------------------------------------------------------------
' EVENTS
' -------------------------------------------------------------------------------------------------------------------

SUB OnInit()
CoInitialize(0)
SeedRandomNumbers() ' randomize number generation

' init animation library
HRESULT hr = UIAnimationInit(&OnAnimationTick)
IF hr > 0 THEN
_MessageBox(0, "The initialization has failed with code: " + STR$(hr), " Windows Animation Manager", 0)
_SendMessage(w1.hwnd, WM_CLOSE, 0, 0)
RETURN
ENDIF

' init direct2d library
hr = D2DInit()
IF hr > 0 THEN
_MessageBox(0, "The initialization has failed with code: " + STR$(hr), " Direct2D", 0)
_SendMessage(w1.hwnd, WM_CLOSE, 0, 0)
RETURN
ENDIF

' create the direct2d render target
WINRECT rc
GetClientRect(w1.hwnd, rc)
render = D2DRenderTargetCreate(w1.hwnd, rc.right, rc.bottom)

' initial background color
red = 255
green = 255
blue = 255

' create animation variables
redvar = UIAnimationVariableAdd(red, 0, 255) ' initial, min, max
greenvar = UIAnimationVariableAdd(green, 0, 255)
bluevar = UIAnimationVariableAdd(blue, 0, 255)

OnPaint() ' draw the initial state
ENDSUB

SUB OnClose()
' delete animmation variables
UIAnimationVariableRemove(redvar)
UIAnimationVariableRemove(greenvar)
UIAnimationVariableRemove(bluevar)

' delete the storyboard if still exists
IF storyboard THEN UIAnimationStoryboardRemove(storyboard)

' finish the animation library
UIAnimationFinish()

' destroy direct2d render target
D2DRenderTargetDestroy(render)

' finish direct2d library
D2DFinish()

CoUninitialize()
ENDSUB

SUB OnPaint()
Paint()
SETCAPTION (w1, "Click to animate the background color" + "   -   R:" + STR$(red) + "    G:" + STR$(green) + "    B:" + STR$(blue) + "         ")
ENDSUB

SUB OnSize()
UpdateSize()
ENDSUB

' -------------------------------------------------------------------------------------------------------------------
' DIRECT2D ROUTINES
' -------------------------------------------------------------------------------------------------------------------

SUB Paint()
D2DRenderBegin(render)
D2DFillSolidColor(render, red, green, blue, 255)
D2DRenderEnd(render)
ENDSUB

SUB UpdateSize()
WINRECT rc
GetClientRect(w1.hwnd, rc)
D2DRenderTargetResize(render, rc.right, rc.bottom) ' update render target area
ENDSUB

' -------------------------------------------------------------------------------------------------------------------
' ANIMATION ROUTINES
' -------------------------------------------------------------------------------------------------------------------

SUB AnimateBackroundColor(INT red, INT green, INT blue) ' this function encapsulates the whole animation info
' create a new storyboard
storyboard = UIAnimationStoryBoardAdd(storyboard) ' this will delete the current storyboard and create a new one

IF storyboard THEN
' create one transition per variable
pointer transitionred = UIAnimationTransitionAccDecAdd(1.0, red, 0.5, 0.5) ' duration, final value, acc ratio, dec ratio
pointer transitiongreen = UIAnimationTransitionAccDecAdd(1.0, green, 0.5, 0.5)
pointer transitionblue = UIAnimationTransitionAccDecAdd(1.0, blue, 0.5, 0.5)

' comunicate the transition with its variable
UIAnimationStoryBoardTransitionJoin(storyboard, transitionred, redvar)
UIAnimationStoryBoardTransitionJoin(storyboard, transitiongreen, greenvar)
UIAnimationStoryBoardTransitionJoin(storyboard, transitionblue, bluevar)

' play the animation
UIAnimationStoryboardPlay(storyboard)

' delete the transitions (no need to wait till the animation finish)
UIAnimationTransitionRemove(transitionred)
UIAnimationTransitionRemove(transitiongreen)
UIAnimationTransitionRemove(transitionblue)
ENDIF
ENDSUB

SUB OnAnimationTick() ' this function is called every time any animation needs an update
IF UIAnimationStoryboardIsPlaying(storyboard) THEN
' get current values
red = UIAnimationVariableGetCurrentValue(redvar)
green = UIAnimationVariableGetCurrentValue(greenvar)
blue = UIAnimationVariableGetCurrentValue(bluevar)

' update the window, this will call @IDPAINT
InvalidateRect(w1.hwnd, NULL, NULL)
ENDIF
ENDSUB

' -------------------------------------------------------------------------------------------------------------------
' RANDOM NUMBER GENERATION
' -------------------------------------------------------------------------------------------------------------------

SUB SeedRandomNumbers() ' seeding for the first time only!
srand(GetTickCount())
ENDSUB

SUB GetRandomNumber(INT min, INT max), INT ' range : [min, max]
   RETURN min + _rand() % (max + 1 - min)
ENDSUB

Reference tutorial to create animations:

1) Call UIAnimationInit when the program start
2) Call UIAnimationFinish when the program ends

3) Create one global animation variable per value you need to fade from one value to another (such as position, size, color, or opacity)

4) Create a function to setup your animation:

SUB AnimationFunction()
   4.1) Create a storyboard using UIAnimationStoryBoardAdd. A storyboard is a collection of transitions applied to one or more animation variables over time.
   4.2) Create a transition for each animation variable. Setup the duration in seconds, final value and accelerator rates.
   4.3) Link each animation variable with its transition using UIAnimationStoryBoardTransitionJoin
   4.4) Play the animation using UIAnimationStoryboardPlay
   4.5) Clean up your transitions (no need to wait till the animation finish)
ENDSUB

5) Process the animation tick function, wich is called every time the animation needs an update

SUB OnAnimationTick()
   5.1) Get the current value of each animation variable using UIAnimationVariableGetCurrentValue
   5.2) Update your ui with the current values
ENDSUB
9
General Questions / Re: Editor issues
« Last post by LarryMc on November 17, 2018, 11:49:29 AM »
If I reinstall IWBASIC, do I need to uninstall it first?

Clint
No, if you are using version 3.x
10
Shared INC's and LIB's / Re: Constants search Version 5 - here.
« Last post by Andy on November 17, 2018, 10:14:06 AM »
Fasecero,

You are very very welcome.

Wrote this for pleasure, but it is nice to know it is useful and will be used!

Thanks,
Andy.
 :)
Pages: [1] 2 3 ... 10