Silverfrost Forums

Welcome to our forums

get_filtered_file@

21 Jan 2015 12:17 #15369

It is possible to pass the file name to this subroutine and it will appear in the dialogue box as though you have selected that file, but the 'Open' button does not respond. Only when you have selected a file from the list does it know that a file is actually selected. Can this be changed to accept the original file name as though it has been selected?

Also sometimes when called it will return with a blank file name without ever having displayed the dialogue Ian

21 Jan 2015 1:36 #15372

Hi Ian, for the following I copied several JPG images into the path c:\temp, one of them called 'palmen.jpg'.

      WINAPP

      program test
      implicit none

      include <windows.ins>

      integer*4     anz

      character*5   werte(3)
      character*12  mtext(3),capt
      character*120 ifile,ofile,pfad

      mtext = 'Image       '
      werte(1) = '*.BMP'
      werte(2) = '*.JPG'
      werte(3) = '*.TIF'
      anz   = 3

      capt  = 'Image       '
      ifile = 'palmen.jpg'
      pfad  = 'c:\\temp\'
      call set_open_dialog_path@(pfad)
      ofile = trim(pfad)//char(0)
      call get_filtered_file@(capt,ifile,ofile,mtext,werte,anz,1L)

      print*,ifile
      end

When opening the dialogue, the image 'palmen' is shown as default and will be used after closing the window.

Wilfried

21 Jan 2015 3:18 #15376

Wilfred, Thanks for that, it works as a stand alone program, but when I incorporate it my main program as a stand alone function called from a menu, it exhibits the same problem as before. Even if I type the name by hand, it still fails. I have to click on the file in the list. Regards in desperation. Ian

21 Jan 2015 3:47 #15378

Ian, in the next example I call the selection from a main program and it works. May this help you?

      winapp 
      program test 
      implicit none
      include <windows.ins> 

      external      sel_ima

      integer*4     j
      character*120 pfad,ifile

      common  /my_image/  ifile
      common  /path/      pfad

      pfad  = 'c:\\temp\' 
      ifile = 'pucki_1.jpg' 

      j = winio@('%ca[Test]%sy[3d_thin]%fn[MS SANS SERIF]%ts%ac[Esc]'
     *    //'Input image%ff%40rs%^bt[...]%ff%nl%cn%`7bt[OK]',.96D0,
     *    'exit',ifile,sel_ima)

      print*,ifile 
      end 

      integer*4 function sel_ima()
      implicit none
      include <windows.ins> 

      integer*4     anz
      character*5   werte(3)
      character*12  mtext(3),capt
      character*120 ifile,pfad,pfile

      common  /my_image/  ifile
      common  /path/      pfad

      sel_ima = 1

      mtext = 'Image       ' 
      werte(1) = '*.BMP' 
      werte(2) = '*.JPG' 
      werte(3) = '*.TIF' 
      anz   = 3 

      capt  = 'Image       ' 
      call set_open_dialog_path@(pfad) 
      pfile = trim(pfad)//char(0) 
      call get_filtered_file@(capt,ifile,pfile,mtext,werte,anz,1L) 
      end 

Wilfried with 'i' like him from Northumbria 😉

22 Jan 2015 11:39 #15391

Wilfried, Sorry for spelling your name wrongly, I looked up the Northumbrian chap and he certainly had the 'I' in his name, only very rarely did he have th 'E' so I am confused. Interestingly he seems to have ben written about by St Bede who comes from my hometown of Sunderland; I attended Bede School. However, I will now always remember to spell your name correctly.

I am still in despair as my application is almost identical to yours but the main program is much bigger. I will have to try another solution.

Regards Ian

22 Jan 2015 1:00 #15392

Ian,

do you believe that working or not working of the file selection function depends on the size of the main program? That would be really funny. I think that the open_dialog_path@ command and the zero-termination of the 'pfile' string are necessary, and (of course) the transportation of path and file Name from the main to the function via a common block or a module.

Yes, St Bede and St Wilfrid, hard ancient times 😉

In any case: Good luck! Regards Wilfried

22 Jan 2015 2:43 #15394

It works! Used start_pprocess@ to create a process that only selects files. Then received the result by a message, replied 'thanks' and carried on as normal. Yes it does seem to depend on how big the main progrm is. Post tenabras lux (Bede school motto) Regards Ian

27 Jan 2015 8:02 #15501

Wilfried

why //char(0) is used?

27 Jan 2015 9:10 #15502

I have no idea, and I did not use it in my version. In get_multiple_files@ there is only a single character variable which contains the filter values and these are separated with char(0) and terminated with a further char(0). Looks a bit c++ to me. Ian

28 Jan 2015 11:53 #15513

Dan,

as Ian said, I use //char(0) for zero termination like in C. In many cases it seems to be useful if strings are zero-terminated, so I do this often without knowing if it is really necessary.

Wilfried

27 Feb 2015 3:43 #15767

Ian,

Two things.

The examples for get_filtered_file@ all show a 1 as the last argument, meaning the file must exist. If you use 0 as the last argument, and set the name of the file prior to the call, even if it does not exist in the folder, it will be in the control, ready to be 'selected' by clicking 'Save' (argument=0).

If this does not work for you, and you are on Win7, you may be experiencing the same thing I did which required a 'Update in Place' for Win7. See my latest post on the ClearWin+ forum.

Bill

24 Mar 2015 7:45 #15980

As an update, the UPDATE IN PLACE may have 'worked', but the problem still exists. When compiling with /CHECKMATE, sometimes the GET_FILTERED_FILE@ does not work. Indeed, it consumes a great deal of CPU, then returns a blank file name (which I trap). The /RELEASE version does not do this.

I replaced the call with the appropriate WINIO@ parameters, and the identical behavior is shown (no surprise there).

I have yet to figure out how to invoke the Windows open dialog directly, so if someone can help with that, I'll give it a go!

Bill

24 Mar 2015 8:26 #15982

While the /RELEASE version 'works', it does not properly honor the MUSTEXIST value =0, meaning the file need not exist (allowing typing a new name).

So, I linked the code using 3 different heap and stack allocation values using both the /CHECKMATE and /RELEASE compiled code.

  1. Default: /Heap=1048576 /stack=524288000 (values in decimal) - does not work; /CHECKMATE version does not execute properly at all.

  2. /Heap=3145728 /Stack=157286400 (values decimal) - does not work, /RELEASE and /CHECKMATE does not honor MUSTEXIST, clicking on the browse folders closes the sidebar, and will not re-open.

  3. /Heap=1000000 /Stack=600000 (values decimal) - Works just fine! However, the TextArray issue shows up using these values.

Somewhere, there is middle ground that'll always work (I hope), but if just re-linking using different heap/stack allocations causes different success/failure, this is certainly odd behavior.[/code]

29 Mar 2015 8:37 #16027

Quoted from wahorger

I have yet to figure out how to invoke the Windows open dialog directly, so if someone can help with that, I'll give it a go!

From Windows Vista and up, the new file dialogs are exposed through COM interface. If you know a little bit C++ and have an access to compiler with up to date header files, then it's not too difficult.

Take a look at the:

IFileDialog, IFileOpenDialog and IFileSaveDialog interfaces

I personally use MiniBASIC to write my DLL files, as I don't like C++ and curly braces. It supports 'C' style pointer operations and OOP, so most of the C code syntax is easy to translate.

Anyway, below are two examples. The First example lets you select a folder and second lets you select a file. Remember, the COM stuff uses wide character strings instead of character strings.

First example:

func GetFolder(string title, string buffer)
	CoInitialize(NULL)
	IFileOpenDIalog *pfd = NULL
	HRESULT hr = CoCreateInstance(_CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, _IID_IFileOpenDialog, &pfd)
	if hr >= 0
		FILEOPENDIALOGOPTIONS options
		hr = pfd->GetOptions(&options)
		hr = pfd->SetOptions(options|FOS_PICKFOLDERS)
		hr = pfd->SetTitle(a2w(title))
		hr = pfd->Show(0)
		if hr >= 0
			IShellItem *psi
			wstring *pwszName
			hr = pfd->GetResult(&psi)
			if hr >= 0
				hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pwszName)
				buffer = w2a(#pwszName)
				CoTaskMemFree(pwszName)
				psi->Release()
			endif
		endif
		hr = pfd->Release()
	endif
	CoUninitialize()
endf

Some declarations and helper functions for the second example:

type wstr
	wstring str
endtype


type COMDLG_FILTERSPEC
	wstring *name
	wstring *spec
endtype


func count(string str), int
	int pos = instrr(str,',')
	int pos2 = len(str)
	int count = 0
	if len(str) > 0
		count += 1
		while pos
			count += 1
			pos2 = pos-1
			pos = instrr(pos-1, str, ',')
		endwhile
	endif

	return count
endf

Second example part 1:

func GetFile(string title, string buffer, string names, string specs)
	CoInitialize(NULL)

	int c = count(names)
	if count(specs) <> c
		buffer = ''
		return
	endif

	COMDLG_FILTERSPEC *rgFileTypes = new(COMDLG_FILTERSPEC, c)
	wstr *n = new(wstr, c)
	wstr *s = new(wstr, c)

	int pos = instrr(names,',')
	int pos2 = len(names)
	int i = 0
	while pos
		#n[i].str = a2w(ltrim$(mid$(names,pos+1,pos2-pos)))
		i += 1 
		pos2 = pos-1
		pos = instrr(pos-1,names,',')
	endwhile
	#n[i].str = a2w(ltrim$(mid$(names,pos+1,pos2-pos)))

	for i = 0 to c-1
		#rgFileTypes[c-1-i].name = #n[i].str
	next i

	pos = instrr(specs,',')
	pos2 = len(specs)
	i = 0
	while pos
		#s[i].str = a2w(ltrim$(mid$(specs,pos+1,pos2-pos)))
		i += 1 
		pos2 = pos-1
		pos = instrr(pos-1,specs,',')
	endwhile
	#s[i].str = a2w(ltrim$(mid$(specs,pos+1,pos2-pos)))

	for i = 0 to c-1
		#rgFileTypes[c-1-i].spec = #s[i].str
	next i

Second example part2:

	IFileOpenDIalog *pfd = NULL
	HRESULT hr = CoCreateInstance(_CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, _IID_IFileOpenDialog, &pfd)
	if hr >= 0
		hr = pfd->SetFileTypes(c,#rgFileTypes[0])
		hr = pfd->SetTitle(a2w(title))
		hr = pfd->Show(0)
		if hr >= 0
			IShellItem *psi
			wstring *pwszName
			hr = pfd->GetResult(&psi)
			if hr >= 0
				hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pwszName)
				buffer = w2a(#pwszName)
				CoTaskMemFree(pwszName)
				psi->Release()
			endif
		endif
		hr = pfd->Release()
	endif

	delete n
	delete s
	delete rgFileTypes

	CoUninitialize()
endf
Please login to reply.