by Richard Russell, November 2007
Some dialects of BASIC provide the ability to have multiple pages of graphics, whereby you can draw text and/or graphics into each page and then switch 'instantly' between them. Such a facility could be used for simple animation, or simply to avoid having to redraw the screen (possibly taking a significant time) each time a particular layout is needed by your program. It also has the advantage of 'remembering' the contents of each page without any extra effort by you.
Although BBC BASIC for Windows doesn't provide this facility as a built-in feature, it is relatively easy to achieve by means of calls to the Windows API. The routine PROCpage listed below allows you to create, and subsequently select, up to 15 extra pages (you can increase the number if necessary); it also allows you to delete the new pages when you have finished with them (by passing the parameter -1).
To avoid a resource leak you will probably want your program to incorporate ON CLOSE and ON ERROR routines so that the additional pages can be deleted on exit. For example these routines might be as follows:
ON CLOSE PROCpage(-1) : QUIT ON ERROR PROCpage(-1) : SYS "MessageBox", @hwnd%, REPORT$, 0, 48 : QUIT
Of course you may need to perform other 'cleanup' operations as well as deleting the extra graphics pages, so in that case you can replace the PROCpage(-1) with a call to a more general routine which itself then calls PROCpage.
No specific initialisation is required; when you first select a page it will be created. However for the purposes of demonstration you could initialise and label each of the pages as follows:
FOR Page% = 0 TO 15 PROCpage(Page%) VDU 30 PRINT "This is page ";Page% NEXT
As it stands the PROCpage routine doesn't keep independent text cursor positions for each page, so the VDU 30 is used to home the cursor each time. Neither does the routine keep independent settings for colours, fonts, graphics pointers etc. so you must remember to reset these as required whenever a new page is selected. With some extra complication this could be made automatic (PROCpage would need to store the settings for each page).
Selecting each page as required will obviously depend on the specific requirements of your program, but again for the purposes of demonstration the following code uses the function keys to select the different pages:
REPEAT K% = INKEY(10) CASE TRUE OF WHEN K%>=136 AND K%<=139: VDU K%-128 WHEN K%>=145 AND K%<=159: PROCpage(K%-144) WHEN K%=13: VDU 13,10 WHEN K%=-1: OTHERWISE: VDU K% ENDCASE UNTIL FALSE
This code also allows you to write text into each page, to demonstrate that they are truly independent. Note that page 0, which is the normal default screen, cannot be selected using this code. The page currently being displayed is also the page into which text and/or graphics will be drawn, but if you need to draw into one page whilst displaying another this is easily arranged by means of the *REFRESH command.
Finally, here is a listing of the PROCpage routine:
DEF PROCpage(Page%) PRIVATE hdc%() DIM hdc%(15) : REM. Maximum number of pages IF hdc%(0) = 0 hdc%(0) = @memhdc% : REM. Page 0 is default IF Page% >= 0 THEN IF hdc%(Page%) THEN @memhdc% = hdc%(Page%) ELSE LOCAL bitmap%, font%, X%, Y% SYS "GetSystemMetrics", 0 TO X% SYS "GetSystemMetrics", 1 TO Y% SYS "CreateCompatibleBitmap", hdc%(0), X%, Y% TO bitmap% SYS "CreateCompatibleDC", 0 TO @memhdc% SYS "SelectObject", @memhdc%, bitmap% SYS "PatBlt", @memhdc%, 0, 0, X%, Y%, &FF0062 SYS "GetStockObject", 16 TO font% SYS "SelectObject", @memhdc%, font% SYS "SelectPalette", @memhdc%, @hpal% hdc%(Page%) = @memhdc% ENDIF ELSE LOCAL newbm%, oldbm% @memhdc% = hdc%(0) FOR Page% = 1 TO DIM(hdc%(),1) IF hdc%(Page%) THEN SYS "CreateCompatibleBitmap", @memhdc%, 0, 0 TO newbm% SYS "SelectObject", hdc%(Page%), newbm% TO oldbm% SYS "DeleteObject", oldbm% SYS "DeleteDC", hdc%(Page%) ENDIF NEXT ENDIF SYS "InvalidateRect", @hwnd%, 0, 0 ENDPROC