Author |
Topic: A solution to the old FN_setproc problem. (Read 603 times) |
|
sveinioslo
Developer
member is offline


Posts: 64
|
 |
Re: A solution to the old FN_setproc problem.
« Reply #6 on: Aug 18th, 2014, 6:05pm » |
|
Quote:| I cannot reproduce the problem here |
|
Yes, it can sometimes be hard to get the 'oscillatory' effect started. Especially when one wants to. It will never happend while the mouse button is pressed, for some reason. It seems to be a matter of releasing the mousebutton at the right time at the right spot. And both x and y edges of the window must be 'at' or very close to the canvas x y.
Don't think this is pc-specific, tried it on: Win7 pro 32bit core i7 3.4gHz stationary bbc 5.95a Win7 home 64bit core i7 ?gHz laptop new bbc 5.95a Win7 pro dual core 1.6gHz laptop old bbc 5.93a
Quote:Quote:
I also inserted this line into PROCmove() to slow down the oscillations by pressing the shift key.
Adding that code causes resizing and scrolling to happen slowly, but I don't observe any 'oscillatory' effect |
|
Oscillation can be so quick that one can hardly see it, unless one know or expect it to happend, pressing shiftkey when the display seems to flicker, will reveal the oscillation. It is not always the same pattern or frequency. Quote:| That is the automatic behaviour of Windows scrollbars - you don't need to take any special measures to achieve it. Indeed, if I reduce the canvas to 800x600 and then drag the window to a larger size, the scroll bars disappear |
|
Yes. If window<canvas we get and want bars If window>canvas we have no bars and we don't need them If window=canvas we will get bars, but they are not needed If we resize window larger than canvas, we get visible empty unusable areas to the bottom or left of the active window area. To have window=canvas with no bars we need make six.nPage%=canvas+1 Trying to adjust the window with SYS "SetWindowPos" will make it very much easier to get the 'oscillatory' effect. It seems both "SetScrollInfo" and "SetWindowPos" sends the WM_SIZE message, and that will get stored in the eventqueue before PROCmove returns to the inner loop of PROC_eventpoll, which picks up the messages and calls PROCmove again, indefinitely sometimes. One can put say: CNT%+=1 in the inner loop of PROC_eventpoll and open variable viewer to monitor that value. When it starts to rush away, we have the oscillation going. Svein
|
|
Logged
|
|
|
|
sveinioslo
Developer
member is offline


Posts: 64
|
 |
Re: A solution to the old FN_setproc problem.
« Reply #7 on: Aug 18th, 2014, 6:12pm » |
|
Try this one, you will see all kind of malfunctions. A disaster really. Code: SWP_NOMOVE = 2
SWP_NOZORDER = 4
WHITENESS = &FF0062
WM_SIZE = 5
WM_HSCROLL = &114
WM_VSCROLL = &115
WS_HSCROLL = &100000
WS_VSCROLL = &200000
CanvasX% = 800
CanvasY% = 800
WindowX% = 700
WindowY% = 700
IF WindowX%=0 THEN WindowX%=@vdu%!208
IF WindowY%=0 THEN WindowY%=@vdu%!212
IF CanvasX%=0 THEN CanvasX%=WindowX%
IF CanvasY%=0 THEN CanvasY%=WindowY%
SYS "SetWindowPos", @hwnd%, 0, 0, 0, WindowX%, WindowY%, SWP_NOMOVE + SWP_NOZORDER
DIM BITMAPINFOHEADER{Size%, Width%, Height%, Planes{l&,h&}, BitCount{l&,h&}, \
\ Compression%, SizeImage%, XPelsPerMeter%, YPelsPerMeter%, \
\ ClrUsed%, ClrImportant%}
DIM bmi{Header{} = BITMAPINFOHEADER{}}
bmi.Header.Size% = DIM(BITMAPINFOHEADER{})
bmi.Header.Width% = CanvasX%
bmi.Header.Height% = CanvasY%
bmi.Header.Planes.l& = 1
bmi.Header.BitCount.l& = 24
SYS "CreateDIBSection", @memhdc%, bmi{}, 0, ^Bits%, 0, 0 TO hbitmap%
IF hbitmap% = 0 ERROR 100, "Couldn't create DIBSection"
SYS "SelectObject", @memhdc%, hbitmap% TO oldhbm%
SYS "DeleteObject", oldhbm%
INSTALL @lib$+"EVENTLIB"
PROC_eventinit
PROC_eventregister(WM_SIZE, PROCmove())
PROC_eventregister(WM_HSCROLL, PROCmove())
PROC_eventregister(WM_VSCROLL, PROCmove())
REM SYS "GetWindowLong", @hwnd%, -16 TO ws%
REM SYS "SetWindowLong", @hwnd%, -16, ws% OR WS_HSCROLL OR WS_VSCROLL
VDU 23,22,WindowX%;WindowY%;8,16,16,128
ORIGIN 0,2*(@vdu%!212-CanvasY%)
VDU 24,0;0;CanvasX%*2-2;CanvasY%*2-2;
CLG
LINE 0,0,CanvasX%*2-2,CanvasY%*2-2
LINE 0,CanvasY%*2-2,CanvasX%*2-2,0
VDU 23,23,2;0;0;0;
OFF : VDU 5 : VDU 30
MOVE 0,CanvasY%*2-200
REPEAT
WAIT 10
cx% = RND(CanvasX%*2)
cy% = RND(CanvasY%*2)
cr% = RND(200)
GCOL RND(15)
CIRCLE FILL cx%, cy%, cr%
GCOL 0
CIRCLE cx%, cy%, cr%
GCOL 4,0
MOVE cx%-8*INTLOG(cr%)-8,cy%+16
IF cr% > 24 PRINT ;cr%;
PROC_eventpoll
PROCscroll(-1)
UNTIL FALSE
END
DEF PROCscroll(Y%)
PRIVATE S%
IF S% THEN ENDPROC
S%=TRUE
LOCAL rc{}
DIM rc{l%,t%,r%,b%}
SYS "GetRgnBox", @vdu.hr%, rc{}
SYS "ScrollDC", @memhdc%, 0, Y%, rc{}, 0, 0, 0
SYS "ScrollWindow", @hwnd%, 0, Y%, 0, 0
IF Y%<0 THEN
SYS "PatBlt", @memhdc%, 0, CanvasY%-ABS(Y%), CanvasX%, ABS(Y%), WHITENESS
ELSE
SYS "PatBlt", @memhdc%, 0, 0, CanvasX%, ABS(Y%), WHITENESS
ENDIF
REM PROCclr(Bits%,CanvasX%*ABS(Y%),255)
S%=FALSE
ENDPROC
DEF FNTAB(X%,Y%) : X% = X%*16 : Y% = 2*CanvasY%-Y%*24
= CHR$25+CHR$4+CHR$(X%)+CHR$(X%DIV256)+CHR$(Y%)+CHR$(Y%DIV256)
DEF PROCclr(B%,C%,A%) : REM b=start c=len a=value
PRIVATE E%
CASE bmi.Header.BitCount.l& OF
WHEN 24 : C%*=3
WHEN 32 : C%*=4
ENDCASE
IF E%=0 THEN
LOCAL F%,G%,H%,I%,L%
DIM E% 45 : L%=E%+45
FOR I%=8 TO 10 STEP 2
P%=E%
[OPT I%
mov edx,eax
shl edx,8
or eax,edx
mov edx,eax
shl edx,16
or eax,edx
mov edx,eax
.H%
mov al,cl
and al,3
jz G%
mov [ebx+ecx],dl
dec ecx
jmp short H%
.G%
mov eax,edx
mov edx,4
shr ecx,2
.F%
mov [ebx],eax
add ebx,edx
loop F%
ret
]
NEXT I%
ENDIF
CALL E%
ENDPROC
DEF PROCmove(msg%,wp%,lp%) : REM ENDPROC
REM PRINT msg%,wp%,lp%
PRIVATE sih{}, siv{}
LOCAL flag%
DIM sih{cbSize%, fMask%, nMin%, nMax%, nPage%, nPos%, nTrackPos%}
DIM siv{cbSize%, fMask%, nMin%, nMax%, nPage%, nPos%, nTrackPos%}
sih.cbSize% = DIM(sih{})
siv.cbSize% = DIM(siv{})
sih.fMask% = 7
siv.fMask% = 7
sih.nMax% = CanvasX%
siv.nMax% = CanvasY%
CASE msg% OF
WHEN WM_SIZE:
sih.nPage% = lp% AND &FFFF
siv.nPage% = lp% >>> 16
LOCAL rc{},xs%,ys%,xmax%,ymax%,flag%,sx%,sy%,hbar%,vbar%
DIM rc{l%,t%,r%,b%}
SYS "GetSystemMetrics", 0 TO xs% : xs%-=20 :REM screen
SYS "GetSystemMetrics", 1 TO ys% : ys%-=20
SYS "GetSystemMetrics", 2 TO sx% : REM scrollbar
SYS "GetSystemMetrics", 3 TO sy%
IF sih.nPage%<CanvasX% THEN hbar%=1 ELSE hbar%=0 : sih.nPage%=CanvasX%+1
IF siv.nPage%<CanvasY% THEN vbar%=1 ELSE vbar%=0 : siv.nPage%=CanvasY%+1
IF CanvasX%>xs% THEN xmax%=xs% ELSE xmax%=CanvasX%+vbar%*sx%
IF CanvasY%>ys% THEN ymax%=ys% ELSE ymax%=CanvasY%+hbar%*sy%
REM IF sih.nPage%=CanvasX% THEN ymax%=ymax%-sy% ELSE ymax%=ymax%+sy%
REM IF siv.nPage%=CanvasY% THEN xmax%=xmax%-sx% ELSE xmax%=xmax%+sx%
rc.r%=xmax% : rc.b%=ymax%
SYS "GetWindowLong", @hwnd%, -16 TO style%
SYS "AdjustWindowRect", rc{}, style%, 0 : REM menu or not ??? , taskbar ??????
xmax%=rc.r%-rc.l% : IF xmax%>xs% THEN xmax%=xs%
ymax%=rc.b%-rc.t% : IF ymax%>ys% THEN ymax%=ys%
SYS "GetWindowRect", @hwnd%, rc{}
rc.r%=rc.r%-rc.l%
rc.b%=rc.b%-rc.t%
IF rc.r% > xmax% THEN
WindowX%=xmax%+vbar%*sx%
flag%=1
ELSE
WindowX%=rc.r%+vbar%*sx%: REM no need to "setwindowpos" unless Y needs
ENDIF
IF rc.b% > ymax% THEN
WindowY%=ymax%+hbar%*sy%
flag%=1
ELSE
WindowY%=rc.b%+hbar%*sy%
ENDIF
IF INKEY(-1) THEN TRACE STEP ON
WHEN WM_HSCROLL:
CASE wp% AND &FFFF OF
WHEN 0: sih.nPos% -= 1
WHEN 1: sih.nPos% += 1
WHEN 2: sih.nPos% -= sih.nPage%
WHEN 3: sih.nPos% += sih.nPage%
WHEN 5: sih.nPos% = wp% >> 16
ENDCASE
WHEN WM_VSCROLL:
CASE wp% AND &FFFF OF
WHEN 0: siv.nPos% -= 1
WHEN 1: siv.nPos% += 1
WHEN 2: siv.nPos% -= siv.nPage%
WHEN 3: siv.nPos% += siv.nPage%
WHEN 5: siv.nPos% = wp% >> 16
ENDCASE
ENDCASE
IF sih.nPos% > sih.nMax%-sih.nPage% sih.nPos% = sih.nMax%-sih.nPage%
IF siv.nPos% > siv.nMax%-siv.nPage% siv.nPos% = siv.nMax%-siv.nPage%
IF sih.nPos% < sih.nMin% sih.nPos% = sih.nMin%
IF siv.nPos% < siv.nMin% siv.nPos% = siv.nMin%
SYS "SetScrollInfo", @hwnd%, 0, sih{}, 1
SYS "SetScrollInfo", @hwnd%, 1, siv{}, 1
@ox% = sih.nPos%
@oy% = siv.nPos%
SYS "InvalidateRect", @hwnd%, 0, 0
*REFRESH
IF flag% THEN SYS "SetWindowPos", @hwnd%, 0, 0, 0, WindowX%, WindowY%, SWP_NOMOVE + SWP_NOZORDER
ENDPROC
|
|
Logged
|
|
|
|
sveinioslo
Developer
member is offline


Posts: 64
|
 |
Re: A solution to the old FN_setproc problem.
« Reply #8 on: Aug 18th, 2014, 6:15pm » |
|
In my coding, that is.!
svein
|
|
Logged
|
|
|
|
rtr
Guest
|
 |
Re: A solution to the old FN_setproc problem.
« Reply #9 on: Aug 18th, 2014, 9:54pm » |
|
on Aug 18th, 2014, 6:05pm, sveinioslo wrote:| Yes, it can sometimes be hard to get the 'oscillatory' effect started. Especially when one wants to. |
|
I've never managed it. All the systems you listed run Windows 7, so it may be associated with that specific version. If you get an opportunity, try it on Windows 8 or 8.1.
Quote:| It seems both "SetScrollInfo" and "SetWindowPos" sends the WM_SIZE message |
|
My expectation would be that SetScrollInfo would send a WM_SIZE message only if it results in a scrollbar appearing (in which case the client size decreases) or a scrollbar disappearing (in which case the client size increases). In those specific cases it is obviously correct to send a WM_SIZE message.
However if, as a result of the SetScrollInfo, a scrollbar neither appears nor disappears, the client size doesn't change and I would not expect a WM_SIZE to be generated. This program confirms that to be the case (on Windows 8.1 at least) since no ON MOVE occurs:
Code: ON MOVE PRINT "ON MOVE received" : RETURN
DIM sih{cbSize%, fMask%, nMin%, nMax%, nPage%, nPos%, nTrackPos%}
DIM siv{cbSize%, fMask%, nMin%, nMax%, nPage%, nPos%, nTrackPos%}
sih.cbSize% = DIM(sih{})
siv.cbSize% = DIM(siv{})
sih.fMask% = 7
siv.fMask% = 7
sih.nMax% = @vdu%!208
siv.nMax% = @vdu%!212
sih.nPage% = sih.nMax%+1
siv.nPage% = siv.nMax%+1
SYS "SetScrollInfo", @hwnd%, 0, sih{}, 1
SYS "SetScrollInfo", @hwnd%, 1, siv{}, 1
REPEAT
WAIT 1
UNTIL FALSE
END That being the case, I do not understand how an 'oscillatory' effect can result, and I do not see one here.
Whatever is going on, EVENTLIB is not to blame because all it does is effectively to lengthen the event queue from 32 to 64 events. Even if you eliminate EVENTLIB's queue entirely, you are still left with the 32-event queue built into BB4W; so the same effect is likely to occur.
Richard.
Edit: I've just tried the above code in Windows 7 - no ON MOVE happens there either. So, if you gradually increase the size of the Window, at one point the scrollbar will disappear. This will result in the client size increasing and a WM_SIZE message being sent - but only one. The increase in the client size cannot result in another WM_SIZE - the scrollbar is still absent.
Similarly, if you gradually decrease the size of the Window, at one point the scrollbar will appear. This will result in the client size decreasing and a WM_SIZE message being sent, but again only one. The decrease in the client size cannot result in another WM_SIZE - the scrollbar is still present.
So how can any kind of 'oscillation' happen? If anything what you have is hysteresis - which is what you want to prevent oscillation! I simply don't understand the mechanism behind what you observe.
|
| « Last Edit: Aug 18th, 2014, 10:45pm by rtr » |
Logged
|
|
|
|
sveinioslo
Developer
member is offline


Posts: 64
|
 |
Re: A solution to the old FN_setproc problem.
« Reply #10 on: Aug 18th, 2014, 11:56pm » |
|
Hmm !?
Just to be clear if this is a windows problem or not. Are you saying that you ran this code on a windows 8 machine, and it just ended. you didn't see a slowly pulsating window ??
Code:SWP_NOMOVE = 2
SWP_NOZORDER = 4
WM_SIZE = 5
INSTALL @lib$+"eventlib"
PROC_eventinit
PROC_eventregister(WM_SIZE, PROCstuck())
SYS "SendMessage",@hwnd%,WM_SIZE,0,0
PROC_eventpoll
END
DEF PROCstuck(m%,w%,l%)
PRIVATE X% : X%+=1 : IF X%>400 X%=0
SYS "SetWindowPos", @hwnd%, 0, 0, 0, 200+X%, 200+X%, SWP_NOMOVE + SWP_NOZORDER
WAIT 1: ENDPROC
Are you also saying that on a windows 8 machine, this code will also just end ??
Code: INSTALL @lib$+"eventlib"
PROC_eventinit
PROC_eventregister(123, PROCstuck())
SYS "SendMessage",@hwnd%,123,0,0
PROC_eventpoll
END
DEF PROCstuck(m%,w%,l%)
SYS "SendMessage",@hwnd%,123,0,0
ENDPROC
If so, then yes, there is a difference between win7 and win8.
Svein
|
|
Logged
|
|
|
|
rtr
Guest
|
 |
Re: A solution to the old FN_setproc problem.
« Reply #11 on: Aug 19th, 2014, 08:42am » |
|
on Aug 18th, 2014, 11:56pm, sveinioslo wrote:| Are you saying that you ran this code on a windows 8 machine, and it just ended. you didn't see a slowly pulsating window ?? |
|
Those programs are not relevant to the issue under discussion. The first sends a SetWindowPos message every time a WM_SIZE message is received, so of course you have deliberately created a feedback mechanism. The second program sends another WM_CONTEXTMENU message every time one is received, so again you have created a feedback mechanism.
If you deliberately create feedback, you can expect unwanted things to happen. Exactly what happens will be difficult to predict, but depending on the system dynamics an oscillatory behaviour is entirely reasonable. For example simply adding delay in the feedback path can dramatically change the system dynamics (in servo-system theory this would be equivalent to changing the phase of the feedback signal).
You may end up with a system which exhibits damped oscillation, which eventually dies down, or a system which exhibits oscillation which builds up until it is limited by a non-linearity. Often the optimum solution is considered to be 'critical damping', which is a non-oscillatory transition to a new steady-state. The mathematics of such systems is well understood, and as an electronics engineer I have plenty of experience of them!
If you are interested in understanding more about servo theory and how to control a system's dynamics, there is plenty of information available online such as:
http://en.wikipedia.org/wiki/Damping
But none of this has any relevance to SCROLL.BBC, which is the program you were reporting problems with. SCROLL.BBC does not contain such a feedback mechanism. When a WM_SIZE message is received, another WM_SIZE message is generated only very rarely - specifically when the SetScrollInfo causes a scrollbar to appear or to disappear. I would not expect SCROLL.BBC to exhibit oscillatory behaviour, and I see no trace of it doing so here.
Richard.
|
|
Logged
|
|
|
|
sveinioslo
Developer
member is offline


Posts: 64
|
 |
Re: A solution to the old FN_setproc problem.
« Reply #12 on: Aug 19th, 2014, 11:56am » |
|
Quote:| Those programs are not relevant to the issue under discussion |
|
They were made specifically to pinpoint IF there is a feedback mechanism, and WHERE it occurs. That is: 'can it be the combination of PROCmove and PROC_eventpoll ?' The answer is a definite yes. Quote:| If you are interested in understanding more about servo theory |
|
We are on the same page here. I worked as an electronics system designer/programmer in the eighties. Not been working with anything remotely close, ever since. Quote:| SCROLL.BBC does not contain such a feedback mechanism. |
|
No, not in it self, but in combination with eventlib it does. You may have missed that there is two consecutive "SetScrollInfo" in PROCmove. They can both send a WM_SIZE. So every WM_SIZE can result in 0,1 or 2 new WM_SIZE.
I am not putting any 'blame' on eventlib, this is just an unfortunate combination that can result in oscillation. The solution is clear: Keep canvas larger than the screen and find another way of dealing with the window resizing And/or Use asynchronous interrupt with a busy flag.
I have made a new video for you, which will provide 'beyond shadow of a doubt' proof. http://fix24.net/bb4w/New_Scroll.bbc.mp4
It is for sure the WM_SIZE message. Svein
|
|
Logged
|
|
|
|
rtr
Guest
|
 |
Re: A solution to the old FN_setproc problem.
« Reply #13 on: Aug 19th, 2014, 1:22pm » |
|
on Aug 19th, 2014, 11:56am, sveinioslo wrote:| That is: 'can it be the combination of PROCmove and PROC_eventpoll ?' The answer is a definite yes. |
|
No. If you create feedback, you can end up with an oscillatory system. That's it. It is irrelevant and unhelpful to refer to specific elements of the system such as PROCmove and PROC_eventpoll. They are no more 'responsible' for the oscillation than, for example, a single resistor or capacitor can be said to be 'responsible' for the oscillation of a hardware circuit.
It is the system as a whole which oscillates. Change any single element within that system and it is likely to change the behaviour.
Quote:The solution is clear: Keep canvas larger than the screen and find another way of dealing with the window resizing And/or Use asynchronous interrupt with a busy flag. |
|
As far as SCROLL.BBC is concerned there is no requirement for a "solution" because there isn't a problem!
Your videos purport to demonstrate a failure mode, but even if that is the case (and I cannot reproduce it here, however hard I try) it happens only over a very narrow range of conditions and it is of trivial significance.
I WILL NOT REPLY TO ANY FURTHER COMMENTS YOU MAY MAKE.
Richard.
|
|
Logged
|
|
|
|
sveinioslo
Developer
member is offline


Posts: 64
|
 |
Re: A solution to the old FN_setproc problem.
« Reply #14 on: Aug 19th, 2014, 2:18pm » |
|
Let's agree to disagree then.  Have a good day.
Svein
|
|
Logged
|
|
|
|
Malvern
Guest
|
 |
Re: A solution to the old FN_setproc problem.
« Reply #15 on: Aug 19th, 2014, 11:24pm » |
|
Just so that you know you are not the only one to see the effect I have made it do it, but it was very difficult to make happen. Win 7 64bit.
I am not going to speculate as to what causes it....
I typically don't use Eventlib but use the methods here https://groups.yahoo.com/neo/groups/bb4w/files/%22Temp%20Folder%22/Event_Programming/
I expect it would show the same issues though as it uses a similar queue.
|
|
Logged
|
|
|
|
Malvern
Guest
|
 |
Re: A solution to the old FN_setproc problem.
« Reply #16 on: Aug 20th, 2014, 04:50am » |
|
Quote:| It is for sure the WM_SIZE message |
|
Yes, certainly that is what I see also. You can single step through the program when this condition arises. The handler for the WM_SIZE event is generating a further WM_SIZE event as it is being handled so the event queue never gets cleared and the oscillation is the effects of some Windows weirdness and the WHILE loop in PROC_eventpoll that never gets its exit condition met. Why Windows doesn't behave as RTR predicted under all circumstances is for Microsoft to know.
|
| « Last Edit: Aug 20th, 2014, 05:28am by Malvern » |
Logged
|
|
|
|
sveinioslo
Developer
member is offline


Posts: 64
|
 |
Re: A solution to the old FN_setproc problem.
« Reply #17 on: Aug 20th, 2014, 09:29am » |
|
Thank you !
Svein
|
|
Logged
|
|
|
|
Malcolm
Guest
|
 |
Re: A solution to the old FN_setproc problem.
« Reply #18 on: Sep 15th, 2014, 6:27pm » |
|
on Aug 20th, 2014, 04:50am, Malvern wrote: The handler for the WM_SIZE event is generating a further WM_SIZE event as it is being handled... |
|
If this is the case couldn't you just put an "ON MOVE LOCAL : RETURN" in the part that deals with WM_SIZE so that the next ON MOVE event(s) that occur within the PROCmove would get ignored?
Malcolm
|
|
Logged
|
|
|
|
|