Using OFN_NOCHANGEDIR flag with GetOpenFileNameA

I have a requirement to present an open file dialog to a user and prevent them from changing the directory from the default. Supposedly, this can be done by setting the Flags field in the OFN_STRUCT to OFN_FILEMUSTEXIST + OFN_PATHMUSTEXIST + OFN_NOCHANGEDIR when calling GetOpenFileNameA, yet I’m not getting any joy. The dialog box appears with the right title, filter list, and default directory, but the Flags don’t seem to take. There is no error on returning control, and the file name is placed in the lpstrFile field as expected. Part of the debugging involved setting the Flags to other values such as OFN_HIDEREADONLY, and none of those work either, except for the OFN_ENABLEHOOK and OFN_ALLOWMULTISELECT flags.

Does anyone have any ideas on how to fix this, or if there’s another option? I don’t want to have to write a procedure to emulate an open file dialog.

Read MSDN OpenFileName page that the OFN_NOCHANGEDIR flag says:

OFN_NOCHANGEDIR 0x00000008
Restores the current directory to its original value if the user changed the directory while searching for files.
This flag is ineffective for GetOpenFileName.

#1 the purpose is to “Restore the Current Directory” i.e. when it returns the Current Directory (i.e. Clarion PATH()) is what it was before the call. Clarion’s FileDialog() has this flag as FILE:KeepDir.

So this is not what you want … but IMO you do want the flag ON. It is usually going to be very very bad for your EXE to suddenly the Current Directory … unless your file names contain the path or you set Prop Data Path.

#2 oddly it says it does Not apply to GetOpenFileName() … which I wonder about. Maybe they mean it does allow changing it while it is open, which could cause problems for a multi-threaded program.

A workaround is to save the LongPath() before the FileDialog() then SetPath(Saved) after. This a good thing to do in Reports because if the Driver is set to write to a file that can change Current Directory.


One way is when FileDialog() returns check the Path of LongPath(FilePicked) not equal LongPath() then show a Message() that file MUST come from the Folder LongPath().

Another way is to make your own File Picker window. It’s not that hard using DIRECTORY() and a LIST.

1 Like

I did that in another life, using SysList. We also implemented the explorer menu, and drag/drop.

Not sure if this is the latest rendition. Been years since I used it. SysList - Browse Files at SourceForge.net

1 Like

One thing I did in Syslist was modify the class so that it cached the icon handles.

Otherwise, it queries the OS for every icon handle every time, even if every file is a PDF.

Caching the icon handles and matching up the extension in a queue made it work really nicely.

Thanks, Jeff.

I downloaded SysList and tried to compile “abcsampl.sln” and got:

File not found or cannot be open: SLIS111X0. LIB. I can’t find the file anywhere in the zip.

What’s that about?

OFN_NOCHANGEDIR: Yeah, I was just thumbing through the different flags and noticed that it wasn’t what I thought it was.

Take a look at the existing .cwproj files, and make one suitable for C11.1 out of it?

You have to build the lib and/or DLL, but this is old, and it needs a cwproj for your version.

1 Like

I think, just rename one, and change the target name.

1 Like

Another thing to keep in mind, that if all you need is a list of files to choose from, you might as well use a good ol’ Clarion listbox.

We needed other functionality that a plain old file picker couldn’t provide.

1 Like

I just use the builtin …
FILEDIALOG('Select File',ioFilename,'*.*',FILE:Longname+FILE:KeepDir)

I’m certain I wasn’t going to be able to do it using GetOpenFileNameA, so I looked at what you had done, and the wndExplorer demo is a great place to start with a window that looks similar. So that’s the solution. Thanks, Jeff!

1 Like

You’re most welcome. To clarify, however, the code that you downloaded was not written by me.