Silverfrost Forums

Welcome to our forums

New format code %cd

6 Jul 2023 8:41 #30419

A new format code %cd (Common Dialog) has been added to the latest release. This provides an alternative to calling routines such as get_filtered_file@. The following sample code illustrates how it works.

winapp
module mm
use clrwin
integer(7) hwnd

contains
integer function openfiles()
integer,parameter:: MAXFILES = 10
character(80) fileName(MAXFILES) !Multi-selection
character(80)  shortFileName
character(80)  initialDir
character(256) dir
fileName = ' '
initialDir = 'C:\techsupport' 
dir = ' '
iw = winio@('%cd[hwndowner]&', hwnd)
iw = winio@('%cd[title='Open Fortran files']&')
iw = winio@('%cd[maxFiles]&', MAXFILES) !Multi-selection
iw = winio@('%cd[file]&',filename)
iw = winio@('%cd[rootDir]&', dir)       !Multi-selection 
iw = winio@('%cd[shortFile]&', shortFileName)
iw = winio@('%cd[initialDir]&',initialDir)
iw = winio@('%cd[filter='Fortran files|*.f95;*.for']&')
iw = winio@('%cd[filter='All files (*.*)']&')
iw = winio@('%cd')
if(iw /= 0)then
  write(10,*) trim(dir)
  do i = 1, iw
    write(10,*) trim(fileName(i))
  end do
endif 
openfiles = 2
end function

integer function saveas()
character(256) fileName
character(80)  initialDir 
fileName = 'test.f95'
initialDir = 'C:\techsupport' 
iw = winio@('%cd[saving]&')
iw = winio@('%cd[title='Save Fortran file as']&')
iw = winio@('%cd[file]&',filename)
iw = winio@('%cd[initialDir]&',initialDir)
iw = winio@('%cd[filter='Fortran files|*.f95;*.for']&')
iw = winio@('%cd[filter='All files (*.*)']&')
iw = winio@('%cd')
if(iw /= 0)then
  write(10,*) trim(fileName)
endif 
saveas = 2
end function
end module

program main
use mm
iw = winio@('%^bb[Open]&',openfiles)
iw = winio@('   %^bb[Save]&',saveas)
iw = winio@('%ff%nl%30.10cw[border,local_font]&',10)
iw = winio@('%hw', hwnd)
end program

resources 
1 24 default.manifest
7 Jul 2023 6:30 (Edited: 18 Dec 2025 11:41) #30420

Here is an short introduction to %cd.

New new format code %cd has be added that generates the standard Microsoft Open/Save As file dialog. This is an alternative to calling get_filtered_file@ or get_multiple_filenames@ and provides greater choice as well as a platform for further development. Here are the options: integer,parameter:: MAXFILES = 10 integer(7) hwnd integer flags character(80) fileName(MAXFILES) !For multi-selection character(80) shortFileName,initialDir character(256) dir iw = winio@('%cd[hwndowner]&',hwnd) iw = winio@('%cd[title='Open Fortran files']&') iw = winio@('%cd[file]&',filename) iw = winio@('%cd[initialdir]&',initialDir) iw = winio@('%cd[flags]&',flags) iw = winio@('%cd[saving]&') iw = winio@('%cd[filter='All files (.)']&') iw = winio@('%cd[maxfiles]&', MAXFILES) iw = winio@('%cd[showreadonly]&') iw = winio@('%cd[shortfile]&',shortFileName) iw = winio@('%cd[rootdir]&',dir)

     [hwndOwner]  is the parent HWND obtained from %hw.
     [title]             is the caption for the dialog.
     [file]              is for the selected file.
     [initialDir]      varies with the operating system but usually provides the initial folder when the dialog is first used.
     [flags]           is the value used in the Microsoft OPENFILENAME structure. ClearWin+ provides a default value that is accessed via the value returned by winio@ during construction. Other bit flags can then be added and set using this option.
     [saving]        provides for a \'Save As\' dialog as opposed to a \'File open\' dialog.
     [filter]          can be used more than once and provides a list of file filters.  An alternative form uses a pipe symbol '|' as in
                   iw = winio@('%cd[filter=\'Fortran files|*.f95;*.for\']&')
     [maxfiles]     is the largest number of files for a multi-selection Open dialog.
     [showreadonly] causes the read only check box to be displayed.
     [rootdir]           is for the selected drive and folder name.
     [shortfile]         is for the selected file or files without the path.
7 Jul 2023 4:00 #30421

Paul,

I'm looking forward to using this!

A question: Is 'browse_for_folder@' and/or 'browse_for_folder1@' extension using this process a possibility or in the plan? My code still crashes when the user selects a 'New Folder' using 'browse_for_folder1@'.

Thanks for creating a new way that is extensible!

Bill

7 Jul 2023 6:07 #30422

Bill

Yes. There are other standard dialogs, like 'browse for folder' that are planned using this approach.

7 Jul 2023 6:47 #30423

Does the ClearWin info request

CLEARWIN_INFO@('FILTER_ITEM_SELECTED')

still function like before?

7 Jul 2023 8:42 #30424

No, but I will aim to take a look and provide something similar.

7 Jul 2023 11:03 #30425

Thanks, Paul.

8 Jul 2023 7:54 #30428

I have added [filter_item_selected] which corresponds to an integer used for both input and output....

integer filter_item_selected filter_item_selected = 0 iw = winio@('%cd[filter_item_selected]&',filter_item_selected)

This index starts at 1. A zero value can be used on input for the default.

CLEARWIN_INFO@('FILTER_ITEM_SELECTED') will also still be available for output.

8 Jul 2023 11:50 #30429

Thanks so very much, Paul!

Bill

26 Aug 2023 5:19 #30523

Paul,

When will [filter_item_selected] be available in a DLL for download?

A couple of observations based on some experimenting today.

[rootdir] and [initialdir] seem to have the same purpose, but this is unclear. Could you elaborate on this?

If [rootdir] is not used and [initialdir] is used, it appears to work just fine.

If I use the same variable to set [rootdir] and [initialdir], I cannot consistently traverse the folder paths up/down. Sometimes it works, sometimes it doesn't. If they are different variables, then I've always been able to traverse.

When specifying filters, if you use the pipe syntax ('|'), then you get the title (name) of the filter but not the specifics on what it is filtering. I can see how this syntax could be helpful! Thanks for having both methods!

I have tried [saving] and it nicely changes the filter title, indicating the user can change the type. However, when I type in a new name without the extent, the name returned does not have the extent appended to it [(just like get_filtered_file@()], so knowing which extent is selected gets more importance [to then use set_suffix1@()].

What I really like about [saving] is that if I select an existing file, it will tell me and allow me to either back out, retry, or cancel. I can use that to remove a lot of additional checking code for over-writing existing files. Awesome.

Still more experimenting to do. If I can come up with a small example of the inconsistent behavior to make it consistent, I'll post it.

28 Aug 2023 6:51 #30524

Bill

[filter_item_selected] will already be available for 64 bits via the latest DLL. Please see the link added to the sticky post dated August 1.

For 32 bits the situation is a little more tricky and, if you need it, I could provide you with a separate download for the latest salflibc.dll.

%cd and routines like get_filtered_file@ make calls to the Microsoft functions GetOpenFileName and GetOpenFileName. These use the OPENFILENAME structure that is described here https://learn.microsoft.com/en-us/windows/win32/api/commdlg/ns-commdlg-openfilenamea.

This link provides details of the expected behaviour for initialdir etc. and indicates that in some respects the behaviour of these functions varies from one operating system to another.

In particular I have noted that, for me, initialdir only works for the first call to these functions within the current instance of the application. It seems to me that there may be no standard outcome.

28 Aug 2023 12:15 #30525

Paul, thanks for the explanation of GetOpenFileName and GetOpenFileName. I will look at these descriptions and check out the link to gain a better understanding. I still have 'playing' to do!

I would appreciate access to the 32-bit salflibc.dll with this capability. Thank you for offering.

Bill

29 Aug 2023 6:42 #30526

Bill

I have sent you a personal message.

29 Aug 2023 2:52 #30527

Paul, thanks for the file. I have a few more questions.

In your message of 06 July, in your short introduction, you indicate [flags] as an option, with the explanation that the value of the current flag is returned during construction so that one can add/delete flags as required. I'm unsure how to do that.

if I include the construct

integer:: flags=0
i=winio@('%cd[flags]&',flags)

this appears to set all the flags to zero and proceed to create the dialog box. 'i' is also zero.

So, I am unsure how to get the current flag values, then to set them. Or, should I just set what I want and be done?

Looking to modify flags to better implement 'can exist', 'must exist', and 'Save As'.

Bill

29 Aug 2023 3:17 #30528

Bill

I think that it is very unlikely that [flags] will be useful.

In the example above, at any point you can examine the iw return value. It will give you the flags value at the current point in the construction.

You can then bitwise 'add to' or 'subtract from' this value and use the modified result with %cd[flags].

You would probably want to do this as the last %cd call.

29 Aug 2023 3:27 #30529

Paul, thanks! This is most helpful, and is exactly what I was looking for.

I think (generally) that you are correct that the flags modification might not be needed.

That said, I have a couple of 'specialized' file selections that could be enhanced by using some of the OPN_* flags being set or reset.

Bill

31 Aug 2023 6:46 #30531

I've been experimenting and also adding this new feature into the production code, and have a additional comments as FWIW to those looking to use this.

First Finding: The explanation of the priority of the common dialog to use directories is convoluted; the MSDN explanation is not easily decipherable by humans. That said, there are some things to be aware of when using certain options. This is the example I am dealing with right now.

I was using a relative folder name '.\IMPORT' as input to '[initialdir]'. I open the first file of three with this, select the file, all is OK. Next, I select the second file, also with a relative path of '.\IMPORT'. Now the folder I am directed to to find the file is: 'C:\DATAFOLDER\IMPORT\IMPORT'. The third file is is now asked for in the folder 'C:\DATAFOLDER\IMPORT\IMPORT\IMPORT'. Get the drift.

All this is in keeping with the hierarchy of folders explanation in the MSDN documentation. get_filtered_file@() did not operate this was because you could set the initial folder for the dialog separately and it did not use the previous settings.

I 'fixed' this by removing the setting of '[initialdir]', and making the '[file]' set to '.\IMPORT\filename.txt' (for example). Now, the folder relative honors the directory to which I am 'attached' in all cases.

Second Finding: I really needed the same functionality as 'can exist' and 'must exist'. To use this, I was able to use the '[flags]' option, get the current default flag bits, and clear the OFN_FILEMUSTEXIST bit.

Similarly, I needed a 'Save As' but without the verification of whether to overwrite or not. Again, used the current state of the flags and removed the OFN_OVERWRITEPROMPT, allowing the Save dialog to be shown, but without requiring verification. One reason is that the file extent you choose is not automatically added to the file you select. For example, if I have the file in a folder 'ABCD.TXT', and type for the file name 'ABCD' and have the '*.txt' specification set then click OK, the file name returned does not have the file extent appended to it, so even if you wanted to verify the overwrite, it wouldn't happen. Some MSDN documentation implies that only 3 character extents can be applied automatically, but I cannot get even that to happen. It is a manual, after-the-fact process to add/modify the file extent, thus doing an overwrite verification in the open/save dialog is not useful.

I am not an MSDN expert by any stretch of the imagination. If anyone has a better understanding OR can shed light on some of these issues, I'd appreciate it!

All that said, it is a much more flexible system to use!

Please login to reply.