by Richard Russell, June 2010

The BBC BASIC OPENIN, OPENOUT and OPENUP functions generally take an unambiguous filename as their parameter. In BBC BASIC for Windows you can instead supply an ambiguous filename, that is a filename containing one or more wildcard characters: ? (standing for a single character) or * (standing for any number of characters).

In that case, since the supplied parameter doesn't specify a unique file, a file selector (Open File dialogue) is displayed, allowing the user to select a file. The files listed are filtered according to the supplied parameter, so in the case of the following code:
      file% = OPENIN("*.ABC")
only files with the extension ABC are (initially) displayed for the user to select from.

If the user chooses to cancel the operation (by clicking the Cancel button in the dialogue box) an Escape error is triggered. This happens even if the Escape key has been disabled using *ESC OFF (see here for a workaround).

When a file has been selected by the user the OPENIN (or OPENOUT, OPENUP) function returns a channel number in the usual way, or zero if the file cannot be opened. There is no official way (in Windows XP and earlier) for the user's program to discover which file the user selected, but the following code can be used to do so:
      file% = OPENIN("*.*")
      filename$ = $$!420
Assuming file% is non-zero, the path and filename of the selected file is placed in the variable filename$.

addition by Michael Hutton, edited by Richard Russell, June 2012
The easiest way of discovering the filename is the above method, but it can also be achieved using the code below, which does not require accessing the interpreter's internal variables. However the API function used is available only on Windows Vista or later, therefore its use will result in your program being incompatible with Windows XP, which is still used in very large numbers:

      file% = OPENIN(file$)
      REM Get the file name if was chosen in dialog
      IF file$="" OR INSTR(file$,"*") OR INSTR(file$,"?") THEN file$ = FN_GetFileNameFromChannel(file%)
 
      PRINT file$  
 
      END
 
      DEF FN_GetFileNameFromChannel(file%)
      MAX_PATH = 260
      LOCAL path%, R% 
      DIM path% LOCAL MAX_PATH+1 : REM +1 Ensures null termination 
      SYS "GetFinalPathNameByHandle", @hfile%(file%), path%, MAX_PATH, 0 TO R%
      IF R%=0 THEN ERROR 100, "Error : GetFinalPathNameByHandle"
      = $$(path%+4) : REM excludes the leading //?/