Table of Contents
Using an ATL container control
by Richard Russell, November 2006
If, in your BBC BASIC program, you want to display a 'document' file (or other registered file type, such as an image file) you can very easily do that using SYS “ShellExecute”, as described in the main help documentation. However that method causes a separate window to open in which the document is displayed.
You may instead prefer to display the document, image etc. in your own window, as if it is genuinely part of your program. This is relatively easily achieved using an ATL container control. Unlike the ShellExecute method you can only view a document, image etc.; you cannot edit it or save it to file.
The code below shows how to create a file viewer application which can display several different file types, within the confines of your own window. Although this program causes your entire output window to be used for the display, it can easily be adapted to reduce the size of the document window and leave space for other components.
Initialisation
The first step is some necessary initialisation:
INSTALL @lib$+"WINLIB5" SYS "LoadLibrary", "ATL.DLL" TO atl% SYS "GetProcAddress", atl%, "AtlAxWinInit" TO `AtlAxWinInit` SYS `AtlAxWinInit`
Creating a menu
In this example application a simple menu is created, giving the option to open or close the file to be viewed, or to exit the program. You may want to select the file in a different way.
SYS "CreatePopupMenu" TO hfile% SYS "AppendMenu", hfile%, 0, 101, "&Open"+CHR$9+"Ctrl+O" SYS "AppendMenu", hfile%, 0, 102, "&Close" SYS "AppendMenu", hfile%, 0, 103, "E&xit" SYS "CreateMenu" TO hmenu% SYS "AppendMenu", hmenu%, 16, hfile%, "&File" SYS "SetMenu", @hwnd%, hmenu% SYS "DrawMenuBar", @hwnd%
Event handling
The code below handles menu selection and window-resizing events. The latter is to ensure that if your main window is resized by the user, the viewer window is resized to suit:
ON SYS Click% = @wparam% : RETURN ON MOVE PROCmove(@msg%, @wparam%, @lparam%) : RETURN *ESC OFF Click% = 0 hATL% = 0 REPEAT select% = INKEY(1) IF select% = -1 SWAP select%,Click% CASE select% OF WHEN 101, 15: hATL% = FNopen(hATL%) WHEN 102: IF hATL% PROC_closewindow(hATL%) : hATL%=0 WHEN 103: QUIT ENDCASE UNTIL FALSE END
Note that the “END” statement is only included for neatness; it can never be reached. The global variable hATL% is the window handle of the viewer window.
Opening the file
The code below displays a file selector dialogue, and opens the selected file (if any):
DEF FNopen(hw%) LOCAL fs{}, rc{}, fp%, ff$, res% DIM fs{lStructSize%, hwndOwner%, hInstance%, lpstrFilter%, \ \ lpstrCustomFilter%, nMaxCustFilter%, nFilterIndex%, \ \ lpstrFile%, nMaxFile%, lpstrFileTitle%, \ \ nMaxFileTitle%, lpstrInitialDir%, lpstrTitle%, \ \ flags%, nFileOffset{l&,h&}, nFileExtension{l&,h&}, \ \ lpstrDefExt%, lCustData%, lpfnHook%, lpTemplateName%} DIM fp% LOCAL 255 ff$ = "PDF files"+CHR$0+"*.PDF"+CHR$0+"HTML files"+CHR$0+"*.HTM;*.HTML"+CHR$0+ \ \ "Text files"+CHR$0+"*.TXT"+CHR$0+"Image files"+CHR$0+"*.JPG;*.GIF;*.PNG"+ \ \ CHR$0+CHR$0 fs.lStructSize% = DIM(fs{}) fs.hwndOwner% = @hwnd% fs.lpstrFilter% = !^ff$ fs.lpstrFile% = fp% fs.nMaxFile% = 256 fs.flags% = 6 SYS "GetOpenFileName", fs{} TO res% IF res% = 0 THEN = 0 IF hw% PROC_closewindow(hw%) DIM rc{l%,t%,r%,b%} SYS "GetClientRect", @hwnd%, rc{} = FN_createwindow("AtlAxWin", $$fp%, 0, 0, rc.r%-rc.l%, rc.b%-rc.t%, 0, &200000, 0)
If the file is successfully opened the function returns the handle of the viewer window. If you want the viewer window to occupy less that the full area of your output window you can determine the dimensions in a way other than SYS “GetClientRect”.
Window resizing
The code below simply resizes the viewer window to match the client area of your output window. Again you may wish to determine the dimensions differently:
DEF PROCmove(M%, W%, L%) IF M% = 5 IF hATL% SYS "SetWindowPos", hATL%, 0, 0, 0, L% AND &FFFF, L% >>> 16, 6 ENDPROC
For more information on the Active Template Library consult Microsoft's ATL Reference.