I have a custom CFileDialog, and I need to perform some operations when the selection changes. I override the OnFileNameOK, OnFileNameChange, and OnFolderChange methods, and in all cases get the list of selected files. Because there's no good way to do this, I call 'GetFileName()' to get the list, and do some parsing. This seems to work alright as long as the user selects only files. However if the user clicks off in the empty area of the list (clearing the selection) or selects a folder, GetFileName returns the previously-selected files instead of the current selections (which I'd expect to be an empty string in the case where no file was selected).
I could get a pointer to the underlying CListCtrl object and iterate the selections, but that has its own set of problems (For one, I'd have to build the full path then try to determine whether a folder or file was selected. For two, if the user his hiding extensions of known types, then I wouldn't know what to do with the files). I've done some research and found this article (http://msdn.microsoft.com/en-us/magazine/cc301466.aspx), but his solution isn't complete, as it doesn't work for the hidden file extensions.
All of this makes me think there should be a way to access the actual shell interface of the list and use some proper interface methods, however I'm not very familiar with that stuff. Can I get an IFolderView2 pointer to the SHELLDLL_DefView object in the CFileDialog and maybe call 'GetSelection' on that interface? If so, can someone provide some sample code?
Where do you call 'GetFileName()' from?
It doesn't make any sense to call it from OnFolderChange override, for example.
It only makes sense to call it from OnFileNameOK!
I call GetFileName() in the OnFileNameOK, OnFileNameChange, and OnFolderChange overrides. I added a call in 'OnFolderChange' because the user could have had some selected files when they hit the 'Up' button to go up a directory. In this case the selection changes (clears out, actually), so I just wanted to make sure my code processed it. It does seem, however, that when the folder changes, I get an OnFolderChange callback as well as an OnFileNameChange. So it's possible I don't need to override OnFolderChange at all. OnFileNameOK isn't called at all during this process (only when I double-click a file), so at the very least, I need to put the processing in OnFileNameChange.
But regardless, the question remains the same, as in my scenario, the folder doesn't have to change to demonstrate the issue I'm trying to resolve.
I provided details about what I'm doing right now so people don't suggest things I've already tried. The details about why aren't important. The only thing that's relevant is what I'm trying to accomplish in general. To put it simply, in my CFileDialog derivative, every time the selection changes in the list control, I want to obtain a list of the absolute paths of the currently selected files (the 'why' doesn't matter). My current approach works so long as the selection changes to another file. However if a folder is selected or all the selection is cleared, my approach doesn't work. So I'm looking for a more robust approach, and that's why I thought there's got to be a way using some shell API I'm not familiar with.
... The details about why aren't important. ...
I want to obtain a list of the absolute paths of the currently selected files (the 'why' doesn't matter). ...
After some (OK, a lot) more research and piecing together little bits from all over the place, I've come up with a solution that seems to work for me. For the sake of other people looking for a similar solution, I'll post it here.
To re-iterate my problem, I wanted my CFileDialog derivative to respond in real time to a selection change, and to process all the selected files (if any). My original solution was to override the 'OnFileNameChange' method, call 'GetFileName' (which would return a space-delimited list of file names), parse it, and append each file to the result of 'GetFolderPath' to generate an absolute path to the file. This worked fine as long as only files were selected. However if the user selected a folder, or clicked off the list entirely to clear the selection, then 'GetFileName' was returning the previous list of selected files rather than the current list (which I would expect to be an empty string).
Attached you'll find my current solution. I've written a helper class (CFileDialogHelper) which I instantiate as a member of my CFileDialog deriviative (heap-based). When I get the 'OnFileNameChange' notification, I call 'GetSelectedFiles' on the helper. Of course, since I'm still relatively unfamiliar with these interfaces, I'm open to other suggestions if someone's got them.
Thanks D_Drmmr. I'm aware of that whole GetParent change that was made, however I tested this solution on both an x64 Windows 7 box and an XP box and it seems to work on both machines. While ugly, I think it'll do the job for now. I wish I didn't have to rely on undocumented behavior, and that the code isn't so nasty looking (I'm sure there's an easier way to do it), but at least it works.
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.