HOWTO: Invoke the "Open With..." Dialog Box Using ShellExecute

ID: Q192352


The information in this article applies to:
  • Microsoft Visual FoxPro for Windows, versions 3.0, 3.0b, 5.0, 5.0a, 6.0


SUMMARY

The WIN32API function ShellExecute and the corresponding FoxPro Foundation Class _shellexecute can both be used to run external programs, as well as open non-executable files if there is a program associated with that file. However, if there is no program associated with the file, ShellExecute and _shellexecute return SE_ERR_NOASSOC (31) and no action is taken upon the file. This article demonstrates how to create a custom class based on _shellexecute (for Visual FoxPro 6.0) and a procedure (for previous versions) that use the "Open With..." dialog box to give the user the option of selecting a program with which to open the file.


MORE INFORMATION

There are two ways to approach this, depending upon the version of FoxPro that is used. When using Visual FoxPro 6.0, the FoxPro Foundation Class _shellexecute can be subclassed and the Shellexecute method overridden. Method 1 describes how to do this. In previous versions of Visual FoxPro, the process must be either executed from a program function or a class will have to be created from scratch. Method 2 describes how to do this as a program function.

Method 1

  1. Create a new class. Make the class name _shelldoc. In the "Based on" field, select the _shellexecute class found in the _environ.vcx class library, which is in the HOME()+"ffc" directory. The class should be stored in a class library named Ztest and not one of the Foundation Classes (FFC) class libraries. Make sure that Ztest resides in the home directory of Visual FoxPro.


  2. When the class designer appears, select the Shellexecute method from the properties window and open it. Insert the following code into the code editor:
    
          *-- Code begins here.
          #define SW_SHOWNORMAL  1
          #define SE_ERR_NOASSOC 31
          liRet = DODEFAULT(tcfilename, tcworkdir, tcoperation)
          IF liRet = SE_ERR_NOASSOC && No association exists
             DECLARE INTEGER GetSystemDirectory IN kernel32.dll ;
                STRING @lsBuffer, ;
                INTEGER liSize
    
             lsSysDir = SPACE(260)  && MAX_PATH, the maximum path length
    
          *-- Get the system directory so that we know
          *-- where Rundll32.exe resides.
             liRet = GetSystemDirectory(@lsSysDir, LEN(lsSysDir))
             lsSysDir = SUBSTR(lsSysDir, 1, liRet)
             lsRun = "RUNDLL32.EXE"
             lsParameters = "shell32.dll,OpenAs_RunDLL "
             liRet = ShellExecute(0, "open", lsRun,;
               lsParameters + tcfilename, lsSysDir, SW_SHOWNORMAL)
          ENDIF
          *-- Code ends here 


  3. Save the class. The class can now be used as in the following example:
    
          *-- Code begins here.
          oShellDoc = NEWOBJECT("_shelldoc",HOME()+"Ztest.vcx")
          oShellDoc.ShellExecute("MyDoc.ZZZ")  && Pass a filename that has
                                               && no association.
          oShellDoc.Release
          *-- Code ends here. 


  4. The "Open with..." dialog box displays if the file has no association. Otherwise, the file opens with the program with which it is associated.


Method 2

  1. Save the following code to a program file and save it as ShellDoc.prg:
    
          *-- Code begins here.
          PROCEDURE ShellDoc()
          LPARAMETERS lsFile
    
          *-- Defines from Winuser.h
          *-- These constants will be used with the
          *-- ShellExecute function.
          #define SW_HIDE             0
          #define SW_SHOWNORMAL       1
          #define SW_NORMAL           1
          #define SW_SHOWMINIMIZED    2
          #define SW_SHOWMAXIMIZED    3
          #define SW_MAXIMIZE         3
          #define SW_SHOWNOACTIVATE   4
          #define SW_SHOW             5
          #define SW_MINIMIZE         6
          #define SW_SHOWMINNOACTIVE  7
          #define SW_SHOWNA           8
          #define SW_RESTORE          9
          #define SW_SHOWDEFAULT      10
          #define SW_FORCEMINIMIZE    11
          #define SW_MAX              11
    
          #define SE_ERR_NOASSOC 31
    
          *-- GetDesktopWindow gives us a window handle to
          *-- pass to ShellExecute.
          DECLARE INTEGER GetDesktopWindow IN user32.dll
          DECLARE INTEGER GetSystemDirectory IN kernel32.dll ;
            STRING @lsBuffer, ;
            INTEGER liSize
    
          *-- ShellExecute is of the following format:
          *--   HINSTANCE ShellExecute(
          *--       HWND hwnd,
          *--       LPCTSTR lpOperation,
          *--       LPCTSTR lpFile,
          *--       LPCTSTR lpParameters,
          *--       LPCTSTR lpDirectory,
          *--       INT nShowCmd
          *--   );
    
          DECLARE INTEGER ShellExecute IN shell32.dll ;
            INTEGER, ;
            STRING @lsOperation, ;
            STRING @lsFile, ;
            STRING @lsParameters, ;
            STRING @lsDirectory, ;
            INTEGER liShowCmd
    
          lsOperation = "open"
          liRet = ShellExecute(GetDesktopWindow(), @lsOperation, @lsFile, ;
            "", "", SW_SHOWNORMAL)
          IF liRet = SE_ERR_NOASSOC && No association exists
             lsSysDir = SPACE(260)  && MAX_PATH, the maximum path length
    
             *-- Get the system directory so that we know
             *-- where Rundll32.exe resides.
             liRet = GetSystemDirectory(@lsSysDir, LEN(lsSysDir))
             lsSysDir = SUBSTR(lsSysDir, 1, liRet)
             lsRun = "RUNDLL32.EXE"
             lsParameters = "shell32.dll,OpenAs_RunDLL "
             liRet = ShellExecute(GetDesktopWindow(), "open", lsRun,;
               lsParameters + lsFile, lsSysDir, SW_SHOWNORMAL)
          ENDIF
          ENDPROC
          *-- Code ends here. 


  2. In the Command window, issue the following command:
    
          SET PROCEDURE TO ShellDoc 


  3. Call the ShellDoc procedure with the following syntax:
    
          DO ShellDoc WITH <cFilename> 
    You may need to pass a path with the file name if the file is on a mapped drive. If <cFilename> has no association, the "Open With..." dialog box appears.



REFERENCES

(c) Microsoft Corporation 1998. All Rights Reserved. Contributions by Mike A. Stewart, Microsoft Corporation.

Additional query words: kbVFp600 kbAPI kbFFC kbvfp300 kbvfp300b kbvfp500 kbvfp500a

Keywords :
Version : WINDOWS:3.0,3.0b,5.0,5.0a,6.0
Platform : WINDOWS
Issue type : kbhowto


Last Reviewed: July 29, 1999
© 2000 Microsoft Corporation. All rights reserved. Terms of Use.