![]() |
Desktop Development »
Shell and IE programming »
General
Advanced
License: The Code Project Open License (CPOL)
Using the Windows RunFile dialog - The documented and undocumented wayBy Armen HakobyanAn article describing how to use system RunFile dialog both documented and undocumented way |
VC6, VC7Win2K, WinXP, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||

In this article I am going to describe how to start the Run file
dialog that you see when launching applications from the Start/Run
menu. There are two ways of doing this - first documented, using the Shell
object, and the second - using the undocumented Windows shell API function
which is much more flexible.
We should create an instance of the Shell object and call its FileRun
method:
// Do not forget to add AfxOleInit() in the InitInstance() of the app !!! BOOL CRunFileDlgDlg::RunDocumented( void ) { IShellDispatch* pShellDisp = NULL; HRESULT hr = ::CoCreateInstance( CLSID_Shell, NULL, CLSCTX_SERVER, IID_IShellDispatch, (LPVOID*)&pShellDisp ); if( hr == S_OK ) { pShellDisp->FileRun(); pShellDisp->Release(); pShellDisp = NULL; } return ( hr == S_OK ); }
We can just launch run file dialog and that is all - it starts stuck to the Start menu.
This way is much more flexible - it allows us to define the dialog icon, title and description. I will not jump in the deeps of the implementation; you can look it in the header and source files I have provided. The function is exported from the shell32.dll by ordinal 61 (dynamically loaded) and its declaration is as follows:
BOOL
FASTCALL
RunFileDlg(
IN HWND hwndOwner, // Owner window, receives notifications
IN HICON hIcon, // Dialog icon handle, if NULL default icon is used
IN LPCTSTR lpszDirectory, // Working directory
IN LPCTSTR lpszTitle, // Dialog title, if NULL default is displayed
IN LPCTSTR lpszDescription, // Dialog description, if NULL default is displayed
IN UINT uFlags // Dialog flags (see below)
);
You can specify one or more of the following values in the uFlags parameter:
RFF_NOBROWSE - Remove the browse button.
RFF_NODEFAULT - No default item selected.
RFF_CALCDIRECTORY - Calculate the working directory from the file
name.
RFF_NOLABEL - Remove the edit box label.
RFF_NOSEPARATEMEM - Remove the Separate Memory Space check box, NT
only.
Other nice feature of this dialog is that it allows us to control which
applications the user should run. When the user selects the OK
button, it sends a notification message with the details of the program, that
should be started, to the window, whose handle you passed in to this function.
The notification is in the form of a WM_NOTIFY message with the wParam
set to RFN_VALIDATE (-510) code and the lParam pointing
to an NMRUNFILEDLG structure:
typedef struct tagNMRUNFILEDLG { NMHDR hdr; // NMHDR structure LPCWSTR lpszFile; // File that should be started LPCWSTR lpszDirectory; // Working directory int nShow; // How an application is to be displayed when open } NMRUNFILEDLG, *LPNMRUNFILEDLG, *PNMRUNFILEDLG;
As far as this is undocumented function, it has differenet signatures in Windows
NT and Windows 9x - Windows NT uses UNICODE version and
Windows 9x - ANSI version despite you call RunFileA
or RunFileW functions. In the implementation the operating system
version is checked and all nesessary conversions are done. But when
handling notificaton message, you should check it once again, because under
Windows NT you will receive NMRUNFILEDLGW and in Windows 9x - NMRUNFILEDLGA,
no matter defined UNICODE or not. See the sample:
// ... // Add the notify handler: // ON_NOTIFY( RFN_VALIDATE, 0, OnRunFileDlgOK ) // ... void CSomeDlg::OnRunFileDlgOK( NMHDR* pNMHDR, LRESULT* pResult ) { LPNMRUNFILEDLG lpNMRFD = (LPNMRUNFILEDLG)pNMHDR; TCHAR szFile[ MAX_PATH ] = { 0 }; #ifndef UNICODE // If NT we get a unicode string anyway. if( ::GetVersion() < 0x80000000 ) // NT4/2K/XP ::WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)lpNMRFD->lpszFile, -1, szFile, 2 * MAX_PATH, NULL, NULL ); #else if( ::GetVersion() > 0x80000000 ) // 95/98/Me ::MultiByteToWideChar( CP_ACP, 0, (LPCSTR)lpNMRFD->lpszFile, -1, szFile, 2 * MAX_PATH ); #endif CString strMsg( _T("") ); strMsg.Format( _T("Run the file %s ?"), szFile ); int nRet = ::MessageBox( GetSafeHwnd(), strMsg, _T("RunFile Dialog notification test"), MB_YESNOCANCEL | MB_ICONQUESTION | MB_DEFBUTTON2 ); switch ( nRet ) { case IDYES: *pResult = RF_OK; break; case IDNO: *pResult = RF_RETRY; break; default: *pResult = RF_CANCEL; } }
//... // In the WindowProc //... case WM_NOTIFY: { LPNMHDR lpNMHDR = (LPNMHDR)lParam; if( lpNMHDR->code == RFN_VALIDATE ) { LPNMRUNFILEDLG lpNMRFD = (LPNMRUNFILEDLG)lpNMHDR; // lpNMRFD->lpszFile ... return RF_OK; } } //...
The return value determines whether the application will be run or not.
You can use the following return values:
RF_OK - Allow the application to run.
RF_CANCEL - Cancel the operation and close the dialog.
RF_RETRY - Cancel the operation, but leave the dialog open.
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 8 Aug 2002 Editor: Chris Maunder |
Copyright 2002 by Armen Hakobyan Everything else Copyright © CodeProject, 1999-2009 Web21 | Advertise on the Code Project |