Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

ModernUI_Spinner Control

Started by fearless, June 28, 2019, 09:38:27 AM

Previous topic - Next topic



   Tried the version from Reply # 12 on my 8.1 laptop.  The six
spinners shown are working well.



I changed the transform and rotation using info from, instead of creating a matrix and rotating and transforming that matrix.
I attach two versions, both use the new transform and rotation, the 1st one scales the width and height based on dpi and uses that measurement for the transform (movement) call. 2nd one uses the width and height as it was before, just from the image size. Not sure if either will work or not but worth a shot.
Only other thought i had was in relation to GdipSetPageScale, on my pc of 1920x1080 GdipGetPageScale returns 1.0, I would imagine on higher dpi it would be a different value, but if its already set (guessing its detected automatically) im unsure if setting this would have any purposeful effect.
Anyhow, hopefully one of those examples works.


Hi fearless
both EXEs produce the same result.

QuoteDoes it show the correct image size for any of those affected spinners - specifically the first image as its just cloned if angle is 0/360, and the 180deg of the image is flipped rather than rotated, so just wondering if any of those appear as quick flashes in those spinners?

On the executable file before the new transformation, those spinners that show completely also rotate. Those who show only a quarter sometimes flicker.



Hi fearless
I've tested the last 2 EXEs on Win7 64bit and they work as expected.
Without knowing what your code looks like, it's hard to say what went wrong and why.
What is for sure, it has something to do with the operating system. Maybe a missing return value, an unpreserved register or something like that.



Thanks for checking that Biterider. Its a head scratcher for sure.

The source for the libraries is available on the github repo: - I didnt upload the most recent changes, but don't think much changed except trying to use hdc and the other transform calls instead of using a matrix

The main function that is used to create the rotated gdi+ images is _MUI_SpinnerRotateCenterImage, which takes the hImage loaded, and the angle, and returns a pBitmap object (gdi+).

The main call chain is

- MUISpinnerLoadImage:
- MUISpinnerAddImage:
- _MUI_SpinnerRotateCenterImage:

If a png is already loaded by user (using some other mechanism), then user can call MUISpinnerAddImage, which internally calls _MUI_SpinnerRotateCenterImage
If using MUISpinnerLoadImage to load a png, it loads it, then calls MUISpinnerAddImage, which internally calls _MUI_SpinnerRotateCenterImage

Returned pBitmap (gdi+ object) is stored in the internal array for frames (which is set to 60 frames max)

I've attached the ModernUI_Spinner source and the source of the MUISpinner1 demo for easier access - the attached ModernUI_Spinner source does have some changes from trying the various things - but should be similar-ish - I commented out some stuff, but can always reference the github version to see what anything was previously - the only function that changed in all the attempts was the _MUI_SpinnerRotateCenterImage function.


Hi fearless
It took me some time to put all in place. I had to download the complete framework to get the missing files.
Unfortunately, my RadASM setup is different than yours, so I had to setup the build chain from scratch.
I got it running to debug, but to look into the compiled libraries I had to include the corresponding source files. Now I got the problem that the linker can not resolve the _WinMainCRTStarup symbol. In case you ask, I changed the name of the entry point to check if this is the problem, but no.
Any clue?  :undecided:


I put the WinMainCRTStartup proc in just as a test to see if it helped with virustotal - it didn't, so you can eliminate that and change it back to the start: and end start normally seen:
    Invoke GetModuleHandle,NULL
    mov hInstance, eax
    Invoke GetCommandLine
    mov CommandLine, eax
    Invoke InitCommonControls
    mov icc.dwSize, sizeof INITCOMMONCONTROLSEX
    Invoke InitCommonControlsEx, offset icc
    Invoke WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT
    Invoke ExitProcess, eax

Could be the linker perhaps? I'm currently using v12 of the linker from a visual studio installation and not the default version that comes with masm32 sdk - this is to support pdb if compiling for debugging so that the symbols can be seen in x64dbg - found the older link didn't work for that.


WinMainCRTStartup and wWinMainCRTStartup are known entry names for MS linker, for GUI application.
May the source be with you


Hi fearless
after hours and hours of debugging, I think I got it  :biggrin: .
It is the GdipRotateMatrix call in the _MUI_SpinnerRotateCenterImage procedure. It requires a fresh FPU, otherwise if fails (at least on Win10).
Check the FPU content anyway. There is a leftover at the beginning of the procedure.



Thanks for looking this, much appreciated.

So I take it if i issue a finit call after finishing with my calcs and before the GdiRotateMatrix it should be ok?
edit: i placed finit during the MUISpinnerAddImage call after the _MUI_SpinnerRotateCenterImage and MUISpinnerAddFrame calls that add or sub the angle just in case it should be reinitialized there as well.

Attached is the recompiled demo after adding in those finit calls to the ModernUI_Spinner library, hopefully its working now


Hi fearless
Good news and bad news  :biggrin:
The good new is that it seems to work,  :thumbsup:
the bad one is that some spinners (#2, #5, #6 & #7) always flicker at the same position. It seems as if a frame is missing.


PS: check the beginning of _MUI_SpinnerRotateCenterImage, it looks like, that after the range, you dont unload a value from the FPU.


Ok thanks.

I took out the code for cloning frames that are at angle 0 and 360. Only does 1 check now for the 180deg -as this throws the image off slightly for some reason - and gives a speed wobble to the spinner, so instead i do the flip image. I slowed down the far right spinner to see if you can see all frames drawn.

I ended up using fstp st(0) to free the fpu from the loaded fAngle now instead. Hopefully that is enough, or maybe the ffree st(0) would be more appropriate here. I spotted an issue in MUISpinnerAddImage where I had commented out the initial store of the angle to begin with (if 0, or 360 for reversed animation) - it was just loading a value into the fpu and not storing it.

So this is the 180 deg fpu code check now:

    finit           ; init fpu
    fld fAngle
    fcom FP4(180.0) ; compare ST(0) with the value of the real4_var variable: 180.0
    fstsw ax        ; copy the Status Word containing the result to AX
    fwait           ; insure the previous instruction is completed
    sahf            ; transfer the condition codes to the CPU's flag register
    fstp st(0)
    ;ffree st(0)
    jz angle_is_180
    jmp other_angle
    ;Invoke GdipDrawImageRectRectI, pGraphicsBuffer, hImage, 0, 0, dwImageWidth, dwImageHeight, 0, 0, dwImageWidth, dwImageHeight, UnitPixel, NULL, NULL, NULL
    Invoke GdipDrawImage, pGraphicsBuffer, hImage, 0, 0
    Invoke GdipImageRotateFlip, pBitmap, Rotate180FlipNone
    jmp tidyup


All other fpu instructions after that load and store into a variable. Let me know if there is any noticeable frames missing still - the 180deg frame for example.


Hi fearless
All is fine now  :thumbsup:  Good job  :eusa_dance:



Ah brilliant! Thanks for your help


Hi fearless:
If You use "fcomp" don't need fstp.
Equations in Assembly: SmplMath