Can I cancel some files in IFileDialogEvents::OnFileOk with Multiple select? - c++

I was wondering if I can cancel some files selected from file dialogs?
This is the method I'm registered to:
https://msdn.microsoft.com/en-us/library/windows/desktop/bb775879(v=vs.85).aspx
I would like to do my custom validations, and the documentation says that I can return S_FALSE to cancel the opening.
If some files fail validation (my custom one) - I want to be able to continue opening just the valid ones.
Current situation, is that I delete the failed files and then the application (word/adobe) says that the file doesn't exist.
I prefer that it won't try to open them (to change the "selected files" somehow)
Is that possible?

Related

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.

MFC CFileDialog open only select files

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.

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.

Adding an item to Internet Explorer's right-click context menu

I'm trying to add a new entry into Internet Explorer's right-click context menu. I understand that this can be achieved by creating an HTML file containing JavaScript, and then linking to this from a location in the registry. I have also read that you can also add the HTML to a resource file and compile it into a DLL (see the Microsoft KB: Adding Entries to the Standard Context Menu). This is where I have started to hit problems.
Here is a bit of background about what I have done so far.
I have the following JavaScript in the file C:\test.htm:
<script type="text/javascript">
alert('Hello, world!');
</script>
I have added a new REG_SZ value 'c:\test.htm' in the registry at the following location:
HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MenuExt
If I now restart IE, my new menu item appears in the context menu. If I select my new menu item, my message box alert appears as expected. So far so good. However, I can't seem to access the script if it's in a DLL. Here are the steps I have taken:
Created a new Visual C++ Class Library project in VS 2005 named 'IETest' in c:\IETest
Imported my C:\test.htm file into the default app.rc resource file. I have changed the ID to be TEST
Compiled the DLL in debug mode
Altered the registry entry to read
res://C:\IETest\debug\IETest.dll/TEST
If I now restart IE and try again, the message box does not appear when I right-click and select my new context menu entry. I have also tried a release build of the DLL without any luck, and also tried replacing the last forward slash with a comma and altering the path single-backslashes to double-slashes.
I can only presume that I've done something wrong when creating my DLL. Can anyone point me in the right direction? Is there any way I can examine the compiled DLL to examine the resources and associated IDs?
Thanks.
Have you tried having the ID be TEST.html? My guess is that IE doesn't know how to handle the file because it doesn't have an extension listed, but this is totally a guess based off the fact that's how certain MS .dlls identify them (i.e. res://c:\windows\system32\shdoclc.dll/navcancl.htm)
The only other thing I can think of is to make sure your resources are of type 23.
ResourceHacker can view the resource files like you want: http://angusj.com/resourcehacker/