btzy / nativefiledialog-extended

Cross platform (Windows, Mac, Linux) native file dialog library with C and C++ bindings, based on mlabbe/nativefiledialog.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to use NFD_OpenDialog(, , , default_path)

Axle-Ozz-i-sofT opened this issue · comments

commented

Hi all
I can't seam to get the NFD_OpenDialog() default path to work. I have checked all of the examples and all are set to NULL.
Windows 10 64-bit GCC MinGWw64.
I have attempted relative paths ".\" "..\" "\xxx" as well as full paths Z:\appdir\xxx
Example:

nfdchar_t* file_path;
nfdfilteritem_t filterItem[2] = {{"Source code", "c"}, {"Headers", "h"}};
nfdchar_t* default_path = ".\\";  /* Z:\\appdir */
nfdresult_t file_ret = NFD_OpenDialog(&file_path, filterItem, 2, default_path);

file_ret == NFD_ERROR (True)

How do I do this?

Best regards
Axle

commented

It took some time to work this out.
A. On Windows, the default folder parameter is only used if there is no recently used folder available. Otherwise, the default folder will be the folder that was last used. Internally, the Windows implementation calls IFileDialog::SetDefaultFolder(IShellItem).
"Once you select a path in the application Windows will ignore any default path you provide as the last file open is stored in the Windows registry."
B. nfde cannot use a relative path. It appears that a fully qualified path must be provided, so you will need to convert any relative path to a fully qualified path before supplying it to NFD_OpenDialog(..., default_path).

How to get around A. if you have already provided a previous path to the application and is now stored in the registry and you wish to test a new default path?

  1. Change the compiled executable name.
  2. Remove the registry entry (*) for the appname last selected path.

Caution! Deleting or changing registry entries comes with risks.
Make a backup (export) of HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32*.*
Remove (delete) the entries between and excluding "default" and "MRUListEx" (numbered from 0 to n).
FirstFolder, LastVisitedPidlMRU LastVisitedPidlMRULegacy.
The numbered list in LastVisitedPidlMRU is the most likely for NT6.x

Retest your app with your new default fully qualified path to confirm that the file dialog opens in the correct directory.
If you don't select a physical file the registry entry will not be created. You can test several paths.
(If you select a path and open/save a file you will see the new entry in the registry editor. Export the entry, remove the ',' and '' and place the hex into a hex editor and you will see the app ID or App name as well as the last opened path. You can delete the single entry and test more default paths.)

Important! Restore your exported backup of as soon as you have finished your tests: HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32*.* imediataly.
I recommend using a virtual machine for the above to be safe.

Axle

Thanks for thoroughly testing it. Yes, that is the correct behaviour of IFileDialog::SetDefaultFolder. Windows also has the IFileDialog::SetFolder function, but that is currently not used by NFD. It might be possible to add a way to call SetFolder after #128 is implemented, as it will allow additional parameters to be added more easily.

About relative paths - I don't think anything in NFD explicitly disables that, so it probably depends on how Windows implements it. Note that any relative path, if supported, will be relative to the current working directory, and not the directory in which your executable is located.

commented

Thanks btzy
"I don't think anything in NFD explicitly disables that, so it probably depends on how Windows implements it."
Anything with a relative path throws NFD_ERROR on Win10 GCC MinGW-w64.
I tried:
The current working directory will be the executable directory during testing.
.\
./ (GCC per-proccessor will convert this to \ on Windows)
.\directory
\direcory
/directory
etc. ...
Only a full path Z:\appdir\subdir or Z:/appdir/subdir works

I had previously used the Allegro native file dialogs addon which always starts in the selected default directory regardless of last selected, so it threw me off. I had forgotten about and wasn't clear on the Windows default behavior :)
I kept trying alternatives not realizing why it kept going to the last file open directory.

I am just looking at using a win/nix implementation of getcwd,_getcwd or realpath or gpakosz/whereami to feed as the default on first start, or ultimately just let it NULL to the user home directory.

Attempting to avoid too much library overhead for a once off that is only ever used the first time the app is run.
I am not certain what the default Linux behavior is on this, but I will find out when I test this on Ubuntu :)

Best regards
Axle