=====Multi-page graphics=====
//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 [[http://www.bbcbasic.co.uk/bbcwin/manual/bbcwin8.html#refresh|*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