MFC CFileDialog open only select files - c++

Using CFileDialog as a file open, I need to allow the user to only select a file that is displayed in the dialog list area, such as by clicking on it. We don't want the user to be able to type in a name in the File Name control. The OPENFILENAME (OFN) struct has several different flags (http://msdn.microsoft.com/en-US/library/ms646839%28v=vs.80%29.aspx), but I don't see one that prevents the user from typing in a filename.
The closest thing I saw was OFN_FILEMUSTEXIST, but that only specifies that the file exists; it still allows the user to type in a name.
Is there any way to do this without inheriting a new class?
MORE INFO
We need to prevent them from typing in a filename because they could open an inappropriate one. With the lpszFilter parameter, we filter the filenames so it only displays files with ABC in the filename (not the extension). So if they typed in a filename, they could enter something like myCoolFileDEF.ext. If the file exists, it will go ahead and let them open it (the dialog will close w/o an error message) even though they were only supposed to open files with ABC in the filename.

Since you are using MFC, just inherit a CFileDialog and disable the file name edit control and combobox. I don't see the point of using CFileDialog AND writing another OFNHookProc callback, though you could start from GetOpenFileName if you want to.

As a previous answer notes, you could root around in the dialog for the filename control and disable it. This is not without penalty though - if you turn on the CFileDialog hook callback logic, you get the "old style" file dialog on Vista and above, not the "new style" one. The "new style" file dialog is a lot more restrictive in what can be customized, and, as far as I know, doesn't provide a supported way to get at the filename control.
Reading your question, my first instinct is that you're over-designing your solution: if you supply a filter then the user has to go to quite a lot of trouble to select the wrong sort of file, and most users won't do that. If they do, it's possible that the user knows better than your program. If it were me, I would just use a filter, then after the file dialog has closed, check the returned filename - if it doesn't match the required pattern, I'd put up a message dialog to ask if the user if they're really sure, and open the file anyway if they insist that they are.

Related

Selectable file formats at file open/save in MFC in Visual C++

My English is not perfect, sorry.
I am using Visual C++ 2019 Community, with MFC.
At CFileDialog class, I wish choose the file encoding: UTF-16 (little/big endian), UTF-8, ANSI, etc, at saving, with or without signature (2 or bytes what signs the encoding, at the begin of the file). This should be contacted to open/save button. In documentation of CFileDialog, I can add only separate buttons, not extending the open/save button like in Visual Studio, LibreOffice, etc. How can I do this? I am beginner with MFC, and desktop programs, but not beginner with C++. Thank you.
In the comments to your question you state:
Yes, I know. But there is no place to write this. Handler of Open menu is built-in part of MFC. At the source code, CFileDialog is not happen. I added handler OnFileOpen(). This has not paramters, empty at now, and the open menu item manages well. So, I do not know to where I type OFN_ALLOWMULTISELCT.
If you look at Technical Note 22 it mentions:
ID_FILE_OPEN Opens an existing document.
Note
You must connect this to your CWinApp-derived class's message map to
enable this functionality.
CWinApp::OnFileOpen has a very simple implementation of calling
CWinApp::DoPromptFileName followed by CWinApp::OpenDocumentFile with
the file or path name of the file to open. The CWinApp implementation
routine DoPromptFileName brings up the standard FileOpen dialog and
fills it with the file extensions obtained from the current document
templates.
One common customization of ID_FILE_OPEN is to customize the FileOpen
dialog or add additional file filters. The recommended way to
customize this is to replace the default implementation with your own
FileOpen dialog, and call CWinApp::OpenDocumentFile with the
document's file or path name. There is no need to call the base class.
As you can see, it states:
The CWinApp implementation
routine DoPromptFileName brings up the standard FileOpen dialog and
fills it with the file extensions obtained from the current document
templates.
But DoPromptFileName seems to be an undocumented function. You can either:
Debug into to MFC source code to see what it does and override it in your own app class,
Continue to roll out your own CWinApp::OnFileOpen override which uses your own CFileDialog.
I suggest you also read up on CFileDialog constructor documentation because it will assist you for basic customization. However, it sounds to me you need to do what #sergiol said in the comments and display your own CFileDialog (using either approach previously described) and add your own combo with your encoding options. Then handle accordingly.
Please note that I have no experience with that level of customization but it should get you going.

How can I open an *modal* file dialog with IFileOpenDialog?

I've been trying to implement a file dialog into my C++ application for a while now, and I achieved good success with the code described in this article (It is german, but the code should be understandable):
https://msdn.microsoft.com/de-de/library/windows/desktop/ff485843(v=vs.85).aspx
However, using this code in my window class, which is a CDialogImpl, I just can't find out how to make this file picker modal. If I use this code, I can just spawn multiple file picker.
Of course, I could just keep track of the state by adding a member variable representing the state, but it would still not solve the problem of being able to click around in the main window while the dialog is opened.
Is there any way which would allow me to make this window modal? I've been trying to scan through all available methods, but I couldn't find anything. I didn't find any flags which could be passed in the creation, neither any options which I could set after creation.
Any help is appreciated!
The example you link to is very simple and has no UI other than the file dialog. Your program is more complex, having a window from which the file dialog is invoked.
You need to provide an owner for the file dialog. When you do that the owner is disabled, part of what makes the dialog modal. Failing to pass an owner means that the other windows are not disabled and so still respond to user input.
The example code provides no owner, but since there are no other windows in that program, that is benign. Modality is only meaningful when there are multiple windows.
So, to solve the problem, pass the owner, the handle of your window, to the Show method of the file dialog.
Disabling owner windows is one of the key parts of a modal dialog. You will find that any API for modal dialogs expects you to specify an owner. Get into the habit of expecting to provide that ownwr window, and looking for the means to do so.

How to prevent "How do you want to open this file" dialog?

In my app I open a report using HTML file as such:
//pStrPath is file:///C:/Users/appts/AppData/Local/Temp/Report_View.htm
ShellExecute(hParentWnd, L"", pStrPath, NULL, NULL, SW_SHOW);
On my development machine it opens up in a web browser, but when I just tested it on a new installation of Windows 10, it showed this dialog instead:
So how can I prevent it from being shown and go with "keep using this app" option from the get-go? Otherwise it may be very confusing for my users.
PS. Note that Edge is installed and can open .htm files if I double-click them.
Referring to Launching Applications (ShellExecute, ShellExecuteEx, SHELLEXECUTEINFO) we note the text
Object Verbs
The verbs available for an object are essentially the items that you find on an object's shortcut menu. To find which verbs are available, look in the registry under HKEY_CLASSES_ROOT\CLSID{object_clsid}\Shell\verb
Commonly available verbs include:
edit - Launches an editor and opens the document for editing.
find - Initiates a search starting from the specified directory.
open - Launches an application. If this file is not an executable
file, its associated application is launched.
print - Prints the document file.
properties - Displays the object's properties.
Given that a double-click is the generally equivalent to selecting "open" in the object's shortcut menu, if we supply the function with the open verb, we can expect the behaviour to mirror that of a user's double-click. - Please see Ken's comment below
As such, we can expect the following code to achieve the desired result.
//pStrPath is file:///C:/Users/appts/AppData/Local/Temp/Report_View.htm
ShellExecute(hParentWnd, L"open", pStrPath, NULL, NULL, SW_SHOW);
If you are trying to open the default program FROM a 32 bit program in 64 bit Windows the ShellExecute and ShellExecuteEX may display the "How do you want to open this file?" dialog box each time. This is due to the way that the default program registered itself in Windows I think.
I could reproduce this error on Windows 11 fresh install where the Photos is set to the Default Program for .jpg files.
In my case, I found that if I use the ShellExecuteExW function and pass the extension into the .lpClass of SHELLEXECUTEINFOW Type that it works.
It should also work with the ShellExecuteExA function
Make sure it's not an exe, reg, bat file, or a URL you are trying to open. It has to be a document type of file.
Use the .lpClass to pass the extension like ".jpg"
Add the SEE_MASK_CLASSNAME As Long = &H1 to the .fMask parameter you are passing in like .fMask = YourMaskValue Or SEE_MASK_CLASSNAME
The reason I think this works is it bypasses any redirection and reads directly from the HKEY_CLASSES_ROOT.jpg

Windows: open a named document

I'm trying to extend an existing app called Drax which edits the metadata of MP4 movie files.. I want to be able to drag-n-drop files onto it, which it does not support. I've gotten far enough to be able to decode the "clipboard" data when it is dropped, and filter to accept only the file (extensions) that I can handle. (Like so but I know next to no winapi/C++ so it's all cargo-culted.)
But now I want to trigger opening the document, whose (file) name I have in a TCHAR. And I'm stuck. How do I trigger the same sort of action the File>Open dialog would, when I know the name of the file from a drag/drop operation?
Normally, the File -> Open dialog does not do anything but allow the user to choose a file name. It then returns this file name to you, the programmer, to do something with.
But, in this case, you're modifying an existing application, so that code has already been written. To find it, you need to search for the method(s) that display the File -> Open dialog. See what they do with the file name(s) returned by the Open dialog.
All the logic for opening the file is very likely to be crammed into the same method as the one that displays the File -> Open dialog. If so, what I would do is refactor the code, so that you have a separate method like
void OpenFile(CString pszFileName, /* other important parameters */)
{
// ...
}
that handles opening the file, specified by a string containing its full path. You will call this method once you get the file name from the File -> Open dialog, and also from elsewhere, like after you get the file name from a drag-drop operation.

How to restrict FileDialog to specific path

Is it possible to restrict a file dialog(open/save) to a specific folder is winapi?
OPENFILENAME fileDialogSettings;
...
fileDialogSettings.lpstrInitialDir = "Some path";
...
if(GetOpenFileName(&fileDialogSettings))
{
}
I want to have "Some path" as root path in the dialog and to restrict navigation to this folder and it's sub folders only. May I use lpfnHook for this?
If you're targeting Vista+ only, you can make use of the IFileDialogEvents::OnFolderChanging method to block the change altogether.
For older versions of Windows, the OpenFileDialog allows you to specify a hook procedure in which you can pick up on the CDN_FOLDERCHANGE notification.
While I can't see any message to disallow the change, you may be able to post a message to tell it to go "back", or just disable the "OK" button.
Another option is to handle CDN_FILEOK notification and refuse paths outside your required directory.
See this MSDN article for more details about the hook procedure.
This question also talks about changing the directory in an open dialog.
Look into OFN_NOCHANGEDIR flag, although the documentation says this:
Restores the current directory to its original value if the user
changed the directory while searching for files.
This flag is ineffective for GetOpenFileName.
Edit: Reading your question again, I guess you don't want the user to navigate up from that directory, not sure if this is possible with GetOpenFileName, you might have to create your own dialog with a directory list view and restrict them that way.