Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
_RESIZE question
#1
When exactly is _RESIZE supposed to detect that a screen has resized?

What I thought is that _RESIZE will change to -1 (TRUE) when the borders are resized manually. However, the SCREEN statement is triggering a _RESIZE as well, but it's not consistent. (see code below)

Having SCREEN trigger a resize makes some sense I suppose, but without consistency it's rather difficult to program for.

Is _RESIZE supposed to be going -1 when the SCREEN statement is used? In my opinion it would be better if it didn't.

Code: (Select All)
$RESIZE:ON

PRINT _RESIZE ' no resize event triggered for SCREEN 0

SLEEP ' REM in front of this line has no effect on SCREEN _NEWIMAGE triggering a resize event

SCREEN _NEWIMAGE(640, 480, 32)

PRINT _RESIZE ' resize event triggered

SLEEP ' REM this line and the SCREEN statement below will not trigger a _RESIZE event

SCREEN _NEWIMAGE(800, 600, 32)

PRINT _RESIZE ' resize only triggered if sleep statement above not REM'ed
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Reply
#2
First, run the following:

Code: (Select All)
$RESIZE:ON
_DELAY .5
PRINT _RESIZE ' no resize event triggered for SCREEN 0
SLEEP ' REM in front of this line has no effect on SCREEN _NEWIMAGE triggering a resize event
SCREEN _NEWIMAGE(640, 480, 32)
_DELAY .5
PRINT _RESIZE ' resize event triggered
SLEEP ' REM this line and the SCREEN statement below will not trigger a _RESIZE event
SCREEN _NEWIMAGE(800, 600, 32)
_DELAY .5
PRINT _RESIZE ' resize only triggered if sleep statement above not REM'ed

Now, as you can see, with that _DELAY in there, _RESIZE prints a resize at each and every step along the way.
When the screen is created, that's a RESIZE.
When we swap to (640, 480, 32), that's a RESIZE.
When we swap to (800, 00, 32), that's a RESIZE.

Remove *ANY* of those _DELAY statements and then run the program and watch 0 become the next result.  

Isn't that odd as heck?!!



The reason for this oddish behavior is just from the way _RESIZE works.  We type in a command to change the screen....  Our compiled EXE starts to change the screen...  The RESIZE flag isn't set until AFTER the change takes place, so it's still 0...   

Now, since most of our SCREEN/WINDOW type commands are all on their own thread/core, the rest of the program is doing it's thing, all La-De-Da, blissfully unaware that the screen is changing.

That PRINT statement is processed, and at this point, _RESIZE is still 0, so it prints 0...

A cycle or two later, the SCREEN stuff is all finished and reset and the RESIZE flag is finally changed...

And you wait until AFTER the next screen change to (640, 480, 32) before asking for it once again, so it's still holding that -1 from the initial screen 0 screen of (80, 25, 0).



RESIZE occurs on a couple of cycles delay from any actual changes.  It's not instant, and that's where you're seeing this type of reporting coming from.

Here's the play-by-play run down of what you're seeing:

$RESIZE:ON     <-- okies, no questions here.

PRINT _RESIZE ' no resize event triggered for SCREEN 0  <-- at this point, the RESIZE even hasn't had time to run through the whole process.  We have no _DELAY for it to take time to trigger and respond to us.

SLEEP <-- no questions here.

SCREEN _NEWIMAGE(640, 480, 32)  <-- we have now triggered a SECOND resize event.

PRINT _RESIZE <-- This prints -1 from the FIRST event, which we haven't polled or reported yet.  The second event hasn't processed yet.

SLEEP <-- all's good here

SCREEN _NEWIMAGE(800, 600, 32)  <-- We now trigger a THIRD resize event.

PRINT _RESIZE   <--  But this one is now printing the -1 from the SECOND resize event.  That 3rd event hasn't processed yet.



I think this little code snippet should clear up things 100% for you:

Code: (Select All)
$RESIZE:ON
PRINT _RESIZE ' no resize event triggered for SCREEN 0
SLEEP ' REM in front of this line has no effect on SCREEN _NEWIMAGE triggering a resize event
SCREEN _NEWIMAGE(640, 480, 32)
PRINT _RESIZE ' resize event triggered
SLEEP ' REM this line and the SCREEN statement below will not trigger a _RESIZE event
SCREEN _NEWIMAGE(800, 600, 32)
PRINT _RESIZE ' resize only triggered if sleep statement above not REM'ed
SLEEP
PRINT "Final Resize:"; _RESIZE
PRINT "And all clear:"; _RESIZE

As you can see, without giving it time to process and report back to us, you're always reporting on PAST events and not the most recent one.  Wink
Reply
#3
And for those curious, here's my initial attempt to determine just how much delay would be necessary for _RESIZE to report properly after a SCREEN statment is issued:

Code: (Select All)
$RESIZE:ON
t# = TIMER(0.001)
FOR i = 1 TO 10
    DO: LOOP UNTIL _RESIZE
    t1# = TIMER(0.001)
    SCREEN _NEWIMAGE(640, 480, 32)
    DO: LOOP UNTIL _RESIZE
    t2# = TIMER(0.001)
    SCREEN _NEWIMAGE(800, 600, 32)
    DO: LOOP UNTIL _RESIZE
    t3# = TIMER(0.001)

    PRINT "Pass "; i; " of 10"
    PRINT USING "##.#### seconds for the first resize to register."; t1# - t#
    PRINT USING "##.#### seconds for the second resize to register."; t2# - t1#
    PRINT USING "##.#### seconds for the second resize to register."; t3# - t2#
    SLEEP
    t# = TIMER(0.001)
    SCREEN _NEWIMAGE(1024, 720, 32)
NEXT
SYSTEM

Note that these times are hardly consistent as you're dealing with the relationship between multiple threads and how they interact, but the longest delay I've seen on my laptop is about 0.18 seconds.   For safety's sake, if I needed to report this without worry for any race condition, I'd probably just toss a _DELAY 0.3 in my program after some SCREEN statement, to make certain that flag and all had time to process before letting the program continue on.   (Or else I'd do like the above, if I was certain _RESIZE was 0 before I issued that SCREEN command.)
Reply
#4
This makes using _RESIZE related statements a real PITA. Sad

In my opinion the SCREEN statement should not trigger a _RESIZE event. The SCREEN statement is given exact dimensions to use that _WIDTH and _HEIGHT will inherit.  Dragging the borders should trigger a _RESIZE event since _RESIZEWIDTH and _RESIZEHIGHT will be needed because exact dimensions can't be resolved while the user is resizing the borders.

I've got code I'm trying to write that auto-adjusts the the client area as the user resizes the borders. This double triggering of _RESIZE and the need to wait for _RESIZE to catch up after a SCREEN statement does not seem right to me.

This code from the $RESIZE page in the Wiki shows this perfectly. If you drag the right border back and forth enough you can eventually get the border stuck in a jitter (you can tell because circles will be drawn while not dragging the border and if you look really closely you'll see the right border jittering slightly).

I'm dealing with this same jitter problem because of SCREEN triggering _RESIZE events.

Code: (Select All)
$RESIZE:ON

SCREEN _NEWIMAGE(160, 140, 32)
_DELAY 0.1
_SCREENMOVE 20, 20
_DISPLAY

' CLEAR _RESIZE FLAG BY READING IT ONCE
temp& = _RESIZE

DO

    _LIMIT 60

    IF CheckResize(_SOURCE) = -1 THEN
        FOR i = 1 TO 10
            CIRCLE (RND * _WIDTH(0) - 1, RND * _HEIGHT(0) - 1), RND * 100 + 5, _RGB32(RND * 255, RND * 255, RND * 255)
        NEXT
    ELSE
        FOR i = 1 TO 200
            PSET (RND * _WIDTH(0) - 1, RND * _HEIGHT(0) - 1), _RGB32(RND * 255, RND * 255, RND * 255)
        NEXT
    END IF

    _DISPLAY

    k& = _KEYHIT

LOOP UNTIL k& = 27 OR k& = 32

SYSTEM



' *************************************************************************************************
' *                                                                                              *
' *  CheckResize: This FUNCTION checks if the user resized the window, and if so, recreates the  *
' *              ORIGINAL SCREEN image to the new window size.                                  *
' *                                                                                              *
' *              Developer Note: You must use $RESIZE:ON, $RESIZE:SMOOTH, or $RESIZE:SMOOTH at  *
' *                              the beginning of your project for this to work.                *
' *                              This FUNCTION only works in QB64 version 1.000 and up.          *
' *                                                                                              *
' *************************************************************************************************
FUNCTION CheckResize (CurrentScreen AS _UNSIGNED LONG)

    ' *** Define local variable for temporary screen
    DIM TempScreen AS _UNSIGNED LONG

    CheckResize = 0

    ' *** Check to see if the user resized the window. If so, change the SCREEN image to the correct size.
    IF _RESIZE THEN

        ' *** First, create a copy of the current SCREEN image.
        TempScreen = _COPYIMAGE(CurrentScreen, 32)

        ' *** Set the SCREEN to the copied image, releasing the current SCREEN image.
        SCREEN TempScreen

        ' *** Remove (FREE) the original SCREEN image.
        _FREEIMAGE CurrentScreen

        ' *** Create a new "original" SCREEN image.
        CurrentScreen = _NEWIMAGE(_RESIZEWIDTH, _RESIZEHEIGHT, 32)

        ' *** Set the SCREEN to the new "original" image, releasing the copied SCREEN image.
        SCREEN CurrentScreen

        '  DRAW PREVIOUS SCREEN ON THE NEW ONE
        _PUTIMAGE (0, 0), TempScreen, CurrentScreen

        _DISPLAY

        ' *** Remove (FREE) the copied SCREEN image.
        _FREEIMAGE TempScreen

        ' *** Tell the caller there was a resize
        CheckResize = -1

    END IF


END FUNCTION
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Reply
#5
You might want to toggle RESIZE OFF before making manual changes, and see if that helps:

Code: (Select All)
$RESIZE:ON
SCREEN _NEWIMAGE(160, 140, 32)
DO: LOOP UNTIL _RESIZE = -1 'wait for the resize flag to trigger
DO: LOOP UNTIL _RESIZE = 0 'be certain to clear all resize flags
_SCREENMOVE 20, 20
_DISPLAY
DO
    _LIMIT 60
    IF CheckResize(_SOURCE) = -1 THEN
        FOR i = 1 TO 10
            CIRCLE (RND * _WIDTH(0) - 1, RND * _HEIGHT(0) - 1), RND * 100 + 5, _RGB32(RND * 255, RND * 255, RND * 255)
        NEXT
    ELSE
        FOR i = 1 TO 200
            PSET (RND * _WIDTH(0) - 1, RND * _HEIGHT(0) - 1), _RGB32(RND * 255, RND * 255, RND * 255)
        NEXT
    END IF
    _DISPLAY
    k& = _KEYHIT
LOOP UNTIL k& = 27 OR k& = 32
SYSTEM
' *************************************************************************************************
' *                                                                                              *
' *  CheckResize: This FUNCTION checks if the user resized the window, and if so, recreates the  *
' *              ORIGINAL SCREEN image to the new window size.                                  *
' *                                                                                              *
' *              Developer Note: You must use $RESIZE:ON, $RESIZE:SMOOTH, or $RESIZE:SMOOTH at  *
' *                              the beginning of your project for this to work.                *
' *                              This FUNCTION only works in QB64 version 1.000 and up.          *
' *                                                                                              *
' *************************************************************************************************
FUNCTION CheckResize (CurrentScreen AS _UNSIGNED LONG)
    ' *** Define local variable for temporary screen
    DIM TempScreen AS _UNSIGNED LONG
    CheckResize = 0
    ' *** Check to see if the user resized the window. If so, change the SCREEN image to the correct size.
    IF _RESIZE THEN
        _RESIZE OFF
        ' *** First, create a copy of the current SCREEN image.
        TempScreen = _COPYIMAGE(CurrentScreen, 32)
        ' *** Set the SCREEN to the copied image, releasing the current SCREEN image.
        SCREEN TempScreen
        ' *** Remove (FREE) the original SCREEN image.
        _FREEIMAGE CurrentScreen
        ' *** Create a new "original" SCREEN image.
        CurrentScreen = _NEWIMAGE(_RESIZEWIDTH, _RESIZEHEIGHT, 32)
        ' *** Set the SCREEN to the new "original" image, releasing the copied SCREEN image.
        SCREEN CurrentScreen
        '  DRAW PREVIOUS SCREEN ON THE NEW ONE
        _PUTIMAGE (0, 0), TempScreen, CurrentScreen
        _DISPLAY
        ' *** Remove (FREE) the copied SCREEN image.
        _FREEIMAGE TempScreen
        ' *** Tell the caller there was a resize
        CheckResize = -1
        _RESIZE ON
    END IF

END FUNCTION
Reply
#6
Good idea, I'll tinker with that.
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Reply




Users browsing this thread: 4 Guest(s)