BBC BASIC for Windows
« A solution to the old FN_setproc problem. »

Welcome Guest. Please Login or Register.
Apr 5th, 2018, 9:57pm



ATTENTION MEMBERS: Conforums will be closing it doors and discontinuing its service on April 15, 2018.
Ad-Free has been deactivated. Outstanding Ad-Free credits will be reimbursed to respective payment methods.

If you require a dump of the post on your message board, please come to the support board and request it.


Thank you Conforums members.

BBC BASIC for Windows Resources
Online BBC BASIC for Windows documentation
BBC BASIC for Windows Beginners' Tutorial
BBC BASIC Home Page
BBC BASIC on Rosetta Code
BBC BASIC discussion group
BBC BASIC for Windows Programmers' Reference

« Previous Topic | Next Topic »
Pages: 1 2  Notify Send Topic Print
 hotthread  Author  Topic: A solution to the old FN_setproc problem.  (Read 596 times)
sveinioslo
Developer

member is offline

Avatar




PM


Posts: 64
xx A solution to the old FN_setproc problem.
« Thread started on: Aug 16th, 2014, 10:54am »

Just got an idea about the old FN_setproc hijacking ON SYS problem.
This appears to be working.
Any comments ?

Svein
Still V.5 user :)

Code:
      WM_COMMAND = 273
      INSTALL @lib$+"WINLIB5"
      ON SYS : PROCa(@wparam%) : RETURN

      a%=FN_button("on sys",300,50,100,30,100,0)
      b%=FN_button("setproc",300,100,100,30,FN_setproc(PROCb),0)
      c%=FN_button("setproc( )",300,150,100,30,FN_setproc(PROCc()),0)

      REPEAT WAIT 0
      UNTIL 0

      DEF PROCa(w%):    PRINT "on sys ";   w%:    ENDPROC
      DEF PROCb:        PRINT "setproc":          ENDPROC
      DEF PROCc(w%,l%): PRINT "setproc() ";w%,l%: ENDPROC

      DEF FN_setproc(RETURN F%)
      PRIVATE D%,T%,lp%
      IF T% = 0 THEN
        LOCAL L%, P%, W%, S%, U%, O%, wp%, code%, pass%, pr%
        DIM code% NOTEND AND 2047, code% 2300, L% -1
        SYS "GetWindowLong", @hwnd%, -4 TO O%
        FOR pass% = 8 TO 10 STEP 2
          P% = code%
          [OPT pass%
          .pr% DD 0
          .wp% DD 0
          .lp% DD 0
          ;REM proc addresses
          ]
          P% = (P% + 2047) AND -2048
          [OPT pass%
          .U%
          pop eax
          push O%
          push eax
          jmp "CallWindowProc"
          .S%                ; subclass
          mov eax,[esp+8]    ; msg
          cmp eax,WM_COMMAND
          jnz U%
          mov eax,[esp+12]   ; wparam
          and eax,&FFFFFF00
          cmp eax,&0000FF00
          jnz U%
          mov eax,[esp+16]   ; lparam
          mov [lp%],eax
          mov eax,[esp+12]   ; wparam
          mov [wp%],eax
          not eax
          and eax,&000000FF
          jz U%
          mov ebx,lp%
          mov eax,[ebx+eax*4]
          or eax,eax
          jz U%
          mov [pr%],eax
          jnz T%
          .W%
          push 0
          call "Sleep"
          .T%
          mov  al,[@vdu%+205]
          add  al,8
          cmp  al,[@vdu%+206]
          jz   W%
          call "csenter"
          mov  edx,[@vdu%-144]
          mov  dl,[@vdu%+205]
          mov  dword [edx+4],pr% ; to @msg%
          mov  dword [edx+260],!^PROC_@sys
          add  dl,8
          mov  [@vdu%+205],dl
          call "csleave"
          or   byte [^@flags%+3],&20
          ret 20
          ]
        NEXT pass%
        SYS "SetWindowLong", @hwnd%, -4, S%
      ENDIF
      D%+=1 : lp%!(D%*4)=F%
      =NOTD%AND&FFFF

      DEF PROC_@sys: IF ?!@msg%=&28 PROC(@msg%)(@msg%!4,@msg%!8) ELSE PROC(@msg%)
      RETURN


 
User IP Logged

rtr
Guest
xx Re: A solution to the old FN_setproc problem.
« Reply #1 on: Aug 16th, 2014, 12:40pm »

on Aug 16th, 2014, 10:54am, sveinioslo wrote:
Just got an idea about the old FN_setproc hijacking ON SYS problem.
This appears to be working. Any comments ?

It seems to work, but I'm unsure what the "problem" is that you are trying to solve.

In my programs I use FN_setproc alone when the only ON SYS events I am interested in are menu selections and/or button clicks (or other simple WM_COMMAND events) and FN_setproc in conjunction with EVENTLIB when I need more flexibility (typically when I use *SYS 1 to enable additional events, which EVENTLIB does automatically):

Code:
      WM_NOTIFY = 78
      INSTALL @lib$+"WINLIB5"
      INSTALL @lib$+"EVENTLIB"

      b%=FN_button("setproc",300,100,100,30,FN_setproc(PROCb),0)
      c%=FN_button("setproc( )",300,150,100,30,FN_setproc(PROCc()),0)

      PROC_eventinit
      PROC_eventregister(WM_NOTIFY, PROCa())

      REPEAT WAIT 0
        PROC_eventpoll
      UNTIL 0

      DEF PROCa(m%,w%,l%): PRINT "notification "; m%,w%,l%: ENDPROC
      DEF PROCb:           PRINT "setproc":                 ENDPROC
      DEF PROCc(w%,l%):    PRINT "setproc() ";w%,l%:        ENDPROC 

So long as you call FN_setproc before PROC_eventinit no "hijacking" takes place: it's one of the main things EVENTLIB was written to achieve (it automatically 'forwards' an unregistered event to the original handler).

Admittedly the use of EVENTLIB forces events to be synchronous (you must call PROC_eventpoll) but in my opinion that's no bad thing.

Richard.
User IP Logged

sveinioslo
Developer

member is offline

Avatar




PM


Posts: 64
xx Re: A solution to the old FN_setproc problem.
« Reply #2 on: Aug 16th, 2014, 7:59pm »

Quote:
but I'm unsure what the "problem" is that you are trying to solve

I was referring to the old pre eventlib problem.
In this post https://groups.yahoo.com/neo/groups/bb4w/conversations/topics/16863 you wrote:
Quote:
The snag with the approach WINLIB5 adopts is that it hijacks ON SYS; if you're using FN_setproc() in your program you can't use ON SYS for anything else

and
Quote:
I would welcome any ideas people might have


I am mostly using eventlib myself, but recently i ran into a problem with it.
While considering options and workarounds, i remembered the old FN_setproc issue, and simply had to try it out.
Pre eventlib we had re-entrant considerations.
Now we have to consider positive feedback instead.
This is obvious when one is aware of the problem.
You probably knew this, but i hadn't thought of it before.
This code shows it clearly.
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
 


Now that i know, i can fix it by as in this example removing the last WM_SIZE message immediately after SetWindowPos.
Code:
        FOR A%=1 TO Q@%(0) STEP 3
          IF Q@%(A%)=WM_SIZE THEN Q@%(A%)=0 : EXIT FOR
        NEXT A%
 

Not saying that there is something wrong with eventlib, just that one needs to be aware of the danger of feedback.
Luckily, my problem was of a visual nature.

Svein

User IP Logged

rtr
Guest
xx Re: A solution to the old FN_setproc problem.
« Reply #3 on: Aug 16th, 2014, 8:39pm »

on Aug 16th, 2014, 7:59pm, sveinioslo wrote:
I was referring to the old pre eventlib problem. In this post https://groups.yahoo.com/neo/groups/bb4w/conversations/topics/16863

As you say, that was pre-EVENTLIB. Indeed, in the message in which I announced the release of EVENTLIB (more than two years ago!) I explicitly said that one of its objectives was to address that specific issue:

on Mar 10th, 2012, 10:17am, admin wrote:
I have written a new BB4W library EVENTLIB:

http://tech.groups.yahoo.com/group/bb4w/files/Libraries/EVENTLIB.BBC

This library is intended to address the issues discussed in these recent threads:

http://tech.groups.yahoo.com/group/bb4w/message/16863
http://tech.groups.yahoo.com/group/bb4w/message/17189
http://tech.groups.yahoo.com/group/bb4w/message/17397
http://tech.groups.yahoo.com/group/bb4w/message/17573

http://bb4w.conforums.com/index.cgi?board=libraries&action=display&num=1331378257

So, naturally, I have not considered it to be a "problem" since! Your 'solution' is a valid alternative approach, which one can use if asynchronous interrupts are wanted, but for my applications I have been happy to use the EVENTLIB method.

Richard.
« Last Edit: Aug 16th, 2014, 8:46pm by rtr » User IP Logged

sveinioslo
Developer

member is offline

Avatar




PM


Posts: 64
xx Re: A solution to the old FN_setproc problem.
« Reply #4 on: Aug 18th, 2014, 2:06pm »

Just checked if your original program had the same problem as mine, and it does.!
Quote:
As another illustration of the use of the EVENTLIB library, I have modified the example program SCROLL.BBC to use it:

http://tech.groups.yahoo.com/group/bb4w/files/Graphics/SCROLL.BBC

By using the new library, window scrolling and re-sizing operations are guaranteed to work properly however quickly you perform them

This is only true if the canvas is bigger than the screen.
As you can see in this video:
http://fix24.net/bb4w/Scroll.bbc.mp4
The only changes i have done, is to make the canvas smaller than my screen.
Code:
      CanvasX% = 800
      CanvasY% = 800
 

I also inserted this line into PROCmove() to slow down the oscillations by pressing the shift key.
Code:
      IF INKEY(-1) WAIT 10
 

What i wanted to do, was to modify your scroll.bbc to add automatic scrollbars to the default bb4w output window.
But they should not be visible until they where needed, as when the window was resized smaller than the canvas.
And to limit resizing up to the canvas size. Then hide scrollbars again.
Sounds very straightforward, right?
Still can't get it to work reliably, there always seems to be an unstable combination of variables.

Can this be one situation where eventlib is not the best choice ?

Svein
User IP Logged

rtr
Guest
xx Re: A solution to the old FN_setproc problem.
« Reply #5 on: Aug 18th, 2014, 2:58pm »

on Aug 18th, 2014, 2:06pm, sveinioslo wrote:
Just checked if your original program had the same problem as mine, and it does!

I cannot reproduce the problem here (Windows 8.1, Intel Core i7 1.90 GHz). If I reduce the canvas size to 800x600 SCROLL.BBC appears still to work perfectly.

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.

Quote:
But they should not be visible until they where needed, as when the window was resized smaller than the canvas.

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.

Quote:
Can this be one situation where eventlib is not the best choice ?

Since I am unable to reproduce the problem I cannot comment. Can you tell us something about your setup, such as the version of Windows, CPU type and speed etc. If I have a more similar machine I will try it on that.

Richard.
User IP Logged

sveinioslo
Developer

member is offline

Avatar




PM


Posts: 64
xx 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
User IP Logged

sveinioslo
Developer

member is offline

Avatar




PM


Posts: 64
xx 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


 
User IP Logged

sveinioslo
Developer

member is offline

Avatar




PM


Posts: 64
xx Re: A solution to the old FN_setproc problem.
« Reply #8 on: Aug 18th, 2014, 6:15pm »

In my coding, that is.!

svein
User IP Logged

rtr
Guest
xx 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 » User IP Logged

sveinioslo
Developer

member is offline

Avatar




PM


Posts: 64
xx 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
User IP Logged

rtr
Guest
xx 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.
User IP Logged

sveinioslo
Developer

member is offline

Avatar




PM


Posts: 64
xx 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
User IP Logged

rtr
Guest
xx 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.
User IP Logged

sveinioslo
Developer

member is offline

Avatar




PM


Posts: 64
xx Re: A solution to the old FN_setproc problem.
« Reply #14 on: Aug 19th, 2014, 2:18pm »

Let's agree to disagree then. smiley
Have a good day.

Svein
User IP Logged

Pages: 1 2  Notify Send Topic Print
« Previous Topic | Next Topic »

| |

This forum powered for FREE by Conforums ©
Terms of Service | Privacy Policy | Conforums Support | Parental Controls