Call win32 api to OpenFileDialog question

Windows specific questions.
PeterHu
Posts: 46
Joined: Jul 24, 2022 4:57

Call win32 api to OpenFileDialog question

Post by PeterHu »

Greetings,

Below code under Win10 fires "else clause" which indicated the open file dialog failed.I struggled to choose the right version between string,zstring ptr,wstring ptr,zstring*n,wstring*n to pass to OPENFILENAME .lpstrFile,lpstrFilter but all faied to open the selected file.

Any help would be appreciated.

Code: Select all


#define UNICODE
#include "windows.bi"
#include "win/commdlg.bi"


sub openFileDialog()

   dim filename as wstring ptr
   filename=allocate(256)
   
   dim filter as wstring ptr
   filter=allocate(256)
   *filter=!"Text Files\0*.txt\0All Files\0*.*\0\0"
   
   dim info as OPENFILENAME
	
   info.lStructSize=sizeof(OPENFILENAME)
   info.lpstrFilter=filter
   info.nMaxFile=len(filename)
   info.lpstrFile=filename
   info.nFilterIndex=1
   info.Flags=OFN_PATHMUSTEXIST or OFN_FILEMUSTEXIST
   
   if(GetOpenFileName(@info)) then
      MessageBox(null,info.lpstrFile,"You picked",0)
   else
      MessageBox(null,"Failed to open the file","Error",MB_OK or MB_ICONEXCLAMATION)
   end if
 end sub
 
 
 print("Testing...")
 openFileDialog()

fxm
Moderator
Posts: 11416
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Call win32 api to OpenFileDialog question

Post by fxm »

First of all:

filename=allocate(256)
*filename = ""


or

filename=callocate(256)
dodicat
Posts: 7650
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Call win32 api to OpenFileDialog question

Post by dodicat »

I have never had much luck with unicode in fb.
So I just use string and zstring.

Code: Select all

'#define UNICODE
#include "windows.bi"
#include "win/commdlg.bi"

Function openFileDialog() As String
    Dim As zstring * 2048 FILE
    Dim As String filter="Text Files(.txt)"+chr(0)+"*.txt"+chr(0)+"All Files"+chr(0)+"*.*"+chr(0,0)
    Dim As OpenFileName SomeFile
    With SomeFile
        .lStructSize = Sizeof(OpenFileName)
        .hInstance = null
        .lpstrFilter = Strptr(filter)
        .lpstrFile = @FILE
        .nMaxFile = 2048
        .nMaxFileTitle = 0
        .lpstrTitle =@"Open"
        .Flags = OFN_PATHMUSTEXIST Or OFN_FILEMUSTEXIST
        .hwndOwner=0
    End With
    if(GetOpenFileName(@SomeFile)) then
      MessageBox(null,SomeFile.lpstrFile,"You picked",0)
   else
      MessageBox(null,"Failed to open the file","Error",MB_OK or MB_ICONEXCLAMATION)
   end if
    Return *SomeFile.lpstrFile
End Function


 
 print("Testing...")
 print openFileDialog()
 sleep
 
PeterHu
Posts: 46
Joined: Jul 24, 2022 4:57

Re: Call win32 api to OpenFileDialog question

Post by PeterHu »

dodicat wrote: Oct 02, 2022 19:56 I have never had much luck with unicode in fb.
So I just use string and zstring.

Code: Select all

'#define UNICODE
#include "windows.bi"
#include "win/commdlg.bi"

Function openFileDialog() As String
    Dim As zstring * 2048 FILE
    Dim As String filter="Text Files(.txt)"+chr(0)+"*.txt"+chr(0)+"All Files"+chr(0)+"*.*"+chr(0,0)
    Dim As OpenFileName SomeFile
    With SomeFile
        .lStructSize = Sizeof(OpenFileName)
        .hInstance = null
        .lpstrFilter = Strptr(filter)
        .lpstrFile = @FILE
        .nMaxFile = 2048
        .nMaxFileTitle = 0
        .lpstrTitle =@"Open"
        .Flags = OFN_PATHMUSTEXIST Or OFN_FILEMUSTEXIST
        .hwndOwner=0
    End With
    if(GetOpenFileName(@SomeFile)) then
      MessageBox(null,SomeFile.lpstrFile,"You picked",0)
   else
      MessageBox(null,"Failed to open the file","Error",MB_OK or MB_ICONEXCLAMATION)
   end if
    Return *SomeFile.lpstrFile
End Function


 
 print("Testing...")
 print openFileDialog()
 sleep
 
This works perfect,as well as it opened and printing file name in MessageBox & in windows console when file name contains asian characters.Thanks.

I am studying the code line by line and a couple of quesions are still in my mind.
No.1 of course is all about the string manipulation in FB esp. in my working environment.Failure to manipulate string correctly and effciently means failure to get work done.I am totally confused at this moment ,why this one is ok while that one is not...
2. !"\0" doesn't work in this case,why
3. When passing a string literal contains asia characters to MessageBox(NULL,SomeFile.lpstrFile,"文件名:",MB_OK or MB_ICONINFORMATION), "文件名:" cann't display correctly; when try to pass to MessageBoxW ,both "文件名:" and someFile.lpstrFile displayed incorrectly.Struggling...
dodicat
Posts: 7650
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Call win32 api to OpenFileDialog question

Post by dodicat »

From the help file Escape sequences:

Note: The zero-character (\000 = \&h00 = \&o000 = \&b00000000) is the null terminator. Only characters before the first null terminator can be seen when the literal is used as a String. To get a zero character in a string use Chr(0) instead.

Code: Select all


print "Text Files(.txt)"+chr(0)+"*.txt"+chr(0)+"All Files"+chr(0)+"*.*"+chr(0,0)

print "Text Files(.txt)"+!"\0"+"*.txt"+!"\0"+"All Files"+!"\0"+"*.*"+!"\0"+!"\0"

print

dim as string s1= "Text Files(.txt)"+chr(0)+"*.txt"+chr(0)+"All Files"+chr(0)+"*.*"+chr(0,0)

dim as string s2= "Text Files(.txt)"+!"\0"+"*.txt"+!"\0"+"All Files"+!"\0"+"*.*"+!"\0"+!"\0"


print s1
print s2
sleep

 
You also have
OpenFileNameW and GetOpenFileNameW.
You could try messing with these, but as I say, I have not studied unicode and codepages much in fb.
I have no need really, British keyboard with plain ascii characters.
The only strange symbol is the pound sign (£), I suppose, chr(163), and I don't know if other systems have this character on their keyboards.
SARG
Posts: 1566
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Call win32 api to OpenFileDialog question

Post by SARG »

dodicat wrote: Oct 03, 2022 8:56 The only strange symbol is the pound sign (£), I suppose, chr(163), and I don't know if other systems have this character on their keyboards.
Yes there is a such symbol on my french keyboard.
But since the Brexit, European Union has decided to remove the symbol £ from keyboard. :twisted: :D :D :D :D
dodicat
Posts: 7650
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Call win32 api to OpenFileDialog question

Post by dodicat »

Oh dear!
That didn't take long.
At this precise time in history it is not worth very much anyway.
But, onwards and upwards, live in hope (and die in poverty??)
dodi :twisted:
SARG
Posts: 1566
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Call win32 api to OpenFileDialog question

Post by SARG »

@dodicat
I hope you understand it was a joke unless something like that is really in the mind of some technocrats. :roll:
PeterHu
Posts: 46
Joined: Jul 24, 2022 4:57

Re: Call win32 api to OpenFileDialog question

Post by PeterHu »

dodicat wrote: Oct 03, 2022 8:56 From the help file Escape sequences:

Note: The zero-character (\000 = \&h00 = \&o000 = \&b00000000) is the null terminator. Only characters before the first null terminator can be seen when the literal is used as a String. To get a zero character in a string use Chr(0) instead.

Code: Select all


print "Text Files(.txt)"+chr(0)+"*.txt"+chr(0)+"All Files"+chr(0)+"*.*"+chr(0,0)

print "Text Files(.txt)"+!"\0"+"*.txt"+!"\0"+"All Files"+!"\0"+"*.*"+!"\0"+!"\0"

print

dim as string s1= "Text Files(.txt)"+chr(0)+"*.txt"+chr(0)+"All Files"+chr(0)+"*.*"+chr(0,0)

dim as string s2= "Text Files(.txt)"+!"\0"+"*.txt"+!"\0"+"All Files"+!"\0"+"*.*"+!"\0"+!"\0"


print s1
print s2
sleep

 
You also have
OpenFileNameW and GetOpenFileNameW.
You could try messing with these, but as I say, I have not studied unicode and codepages much in fb.
I have no need really, British keyboard with plain ascii characters.
The only strange symbol is the pound sign (£), I suppose, chr(163), and I don't know if other systems have this character on their keyboards.
Thanks for the patient help.

Testing under WinFBE64,choosing GB2312 in Environment Options->Themes and Fonts for the source ((WinFBE statusbar indicates ansi mode) can produce output correctly either in MessageBox,in Windows File Open Dialog,or in console regarding ansia character issue mentioned above,.

Code: Select all

'#define UNICODE
#include "windows.bi"
#include "win/commdlg.bi"

Function openFileDialog() As String
    Dim As zstring * 2048 FILE
    Dim As String filter="文本文件(*.txt)"+chr(0)+"*.txt"+chr(0)+"所有文件(*.*)"+chr(0)+"*.*"+chr(0,0)
    'below two only show first line-->Text Files(*.txt)
    'dim as string filter="Text Files(*.txt)"+!"\0"+"*.txt"+!"\0"+"All Files"+!"\0"+"*.*"+!"\0"+!"\0"
    'dim as string filter=!"Text Files(*.txt)\0*.txt\0All Files\0*.*\0\0"
    'print filter
    Dim As OpenFileName SomeFile
    With SomeFile
        .lStructSize = Sizeof(OpenFileName)
        .hInstance = null
        .lpstrFilter = Strptr(filter)
        .lpstrFile = @FILE
        .nMaxFile = 2048
        .nMaxFileTitle = 0
        .lpstrTitle =@"打开文件对话框"
        .Flags = OFN_PATHMUSTEXIST Or OFN_FILEMUSTEXIST
        .hwndOwner=0
    End With
    if(GetOpenFileName(@SomeFile)) then
      MessageBox(null,SomeFile.lpstrFile,"文件名:",0)
   else
      MessageBox(null,"Failed to open the file","Error",MB_OK or MB_ICONEXCLAMATION)
   end if
    Return *SomeFile.lpstrFile
End Function



 print("Testing...")
 print openFileDialog()
 sleep
dodicat
Posts: 7650
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Call win32 api to OpenFileDialog question

Post by dodicat »

I get
File not found, "windows.bi" in '#include "windows.bi"'
When I try WinFBE64 quick run
(But I am able to choose GB2312 )
But I am not a regular user of that ide anyway, so I don't know what is wrong.
But I am pleased you got it all working.
I found a folder browser for you to test.

Code: Select all


#include "windows.bi"
#include "win\shlobj.bi"

Function folderbrowser (Byref title As String = "Choose A Folder") As String
    Dim bi As BROWSEINFO
    Dim pidl As LPITEMIDLIST
    Dim physpath As Zstring * MAX_PATH
    Dim dispname As Zstring * MAX_PATH
    bi.hwndOwner = HWND_DESKTOP
    bi.pszDisplayName = @dispname
    bi.lpszTitle = Strptr(title)
    bi.ulFlags = 0
    bi.lpfn = null
    bi.lParam = 0
    bi.iImage = 0
    pidl = SHBrowseForFolder(@bi)
    If pidl <> 0 Then
        If SHGetPathFromIDList(pidl, physpath) = 0 Then
            Function = ""
        Else
            Function = physpath
        End If
        CoTaskMemFree pidl
    Else
        Function = ""
    End If
End Function

print folderbrowser

sleep

 
Josep Roca
Posts: 557
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

Re: Call win32 api to OpenFileDialog question

Post by Josep Roca »

You can use the IFileOpenDialog interface, declared in "shobjidl.bi".

Example: (change it as needed")

Code: Select all

' ========================================================================================
' Displays the File Open Dialog
' The returned pointer must be freed with CoTaskMemFree
' ========================================================================================
FUNCTION AfxIFileOpenDialog (BYVAL hwndOwner AS HWND, BYVAL sigdnName AS SIGDN = SIGDN_FILESYSPATH) AS WSTRING PTR

   ' // Create an instance of the FileOpenDialog interface
   DIM hr AS LONG
   DIM pofd AS IFileOpenDialog PTR
   hr = CoCreateInstance(@CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, @IID_IFileOpenDialog, @pofd)
   IF pofd = NULL THEN RETURN NULL

   ' // Set the file types
   DIM rgFileTypes(1 TO 3) AS COMDLG_FILTERSPEC
   rgFileTypes(1).pszName = @WSTR("FB code files")
   rgFileTypes(2).pszName = @WSTR("Executable files")
   rgFileTypes(3).pszName = @WSTR("All files")
   rgFileTypes(1).pszSpec = @WSTR("*.bas;*.inc;*.bi")
   rgFileTypes(2).pszSpec = @WSTR("*.exe;*.dll")
   rgFileTypes(3).pszSpec = @WSTR("*.*")
   pofd->lpVtbl->SetFileTypes(pofd, 3, @rgFileTypes(1))

   ' // Set the title of the dialog
   hr = pofd->lpVtbl->SetTitle(pofd, "A Single-Selection Dialog")
      ' // Optional: Allow multiselection
   hr = pofd->lpVtbl->SetOptions(pofd, FOS_ALLOWMULTISELECT)

   ' // Set the folder
   DIM pFolder AS IShellItem PTR
   SHCreateItemFromParsingName (CURDIR, NULL, @IID_IShellItem, @pFolder)
   IF pFolder THEN
      pofd->lpVtbl->SetFolder(pofd, pFolder)
      pFolder->lpVtbl->Release(pFolder)
   END IF

   ' // Display the dialog
   hr = pofd->lpVtbl->Show(pofd, hwndOwner)

   ' // Get the result
   DIM pItem AS IShellItem PTR
   DIM pwszName AS WSTRING PTR
   IF SUCCEEDED(hr) THEN
      hr = pofd->lpVtbl->GetResult(pofd, @pItem)
      IF SUCCEEDED(hr) THEN
         hr = pItem->lpVtbl->GetDisplayName(pItem, sigdnName, @pwszName)
         FUNCTION = pwszName
      END IF
   END IF

   ' // Cleanup
   IF pItem THEN pItem->lpVtbl->Release(pItem)
   IF pofd THEN pofd->lpVtbl->Release(pofd)

END FUNCTION
' ========================================================================================
Call it as:

Code: Select all

DIM pwszName AS WSTRING PTR = AfxIFileOpenDialog(hwnd)
' // Display the name of the selected file
IF pwszName THEN
   MessageBoxW(hwnd, *pwszName, "IFileOpenDialog", MB_OK)
   CoTaskMemFree(pwszName)
END IF
Josep Roca
Posts: 557
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

Re: Call win32 api to OpenFileDialog question

Post by Josep Roca »

With WinFBE, save you file as UTF-16 (BOM) instead of playing with code pages.

You also need to use this define
#define _WIN32_WINNT &h0602
to be able to access the IFileDialog interface.
PeterHu
Posts: 46
Joined: Jul 24, 2022 4:57

Re: Call win32 api to OpenFileDialog question

Post by PeterHu »

dodicat wrote: Oct 05, 2022 10:39 I get
File not found, "windows.bi" in '#include "windows.bi"'
When I try WinFBE64 quick run
(But I am able to choose GB2312 )
But I am not a regular user of that ide anyway, so I don't know what is wrong.
But I am pleased you got it all working.
I found a folder browser for you to test.

Code: Select all


#include "windows.bi"
#include "win\shlobj.bi"

Function folderbrowser (Byref title As String = "Choose A Folder") As String
    Dim bi As BROWSEINFO
    Dim pidl As LPITEMIDLIST
    Dim physpath As Zstring * MAX_PATH
    Dim dispname As Zstring * MAX_PATH
    bi.hwndOwner = HWND_DESKTOP
    bi.pszDisplayName = @dispname
    bi.lpszTitle = Strptr(title)
    bi.ulFlags = 0
    bi.lpfn = null
    bi.lParam = 0
    bi.iImage = 0
    pidl = SHBrowseForFolder(@bi)
    If pidl <> 0 Then
        If SHGetPathFromIDList(pidl, physpath) = 0 Then
            Function = ""
        Else
            Function = physpath
        End If
        CoTaskMemFree pidl
    Else
        Function = ""
    End If
End Function

print folderbrowser

sleep

 
This works perfect with either English or Asian characters,no need to change a single word.
PeterHu
Posts: 46
Joined: Jul 24, 2022 4:57

Re: Call win32 api to OpenFileDialog question

Post by PeterHu »

Josep Roca wrote: Oct 05, 2022 15:46 With WinFBE, save you file as UTF-16 (BOM) instead of playing with code pages.

You also need to use this define
#define _WIN32_WINNT &h0602
to be able to access the IFileDialog interface.
Thank you so much!

When I run in WinFBE with below,it seems that IF pwszName evaluated false so no MessageBoxW pops up ,nor the folder dialog opened.Was I missing something?
DIM pwszName AS WSTRING PTR = AfxIFileOpenDialog(GetModuleHandle(0))
' // Display the name of the selected file
IF pwszName THEN
MessageBoxW(hwnd, *pwszName, "IFileOpenDialog", MB_OK)
CoTaskMemFree(pwszName)
END IF
PaulSquires
Posts: 971
Joined: Jul 14, 2005 23:41

Re: Call win32 api to OpenFileDialog question

Post by PaulSquires »

PeterHu wrote: Oct 06, 2022 3:09 When I run in WinFBE with below,it seems that IF pwszName evaluated false so no MessageBoxW pops up ,nor the folder dialog opened.Was I missing something?
DIM pwszName AS WSTRING PTR = AfxIFileOpenDialog(GetModuleHandle(0))
Why are you passing the EXE's handle using GetModuleHandle to the AfxIFileOpenDialog function instead of a valid Window handle? Pass the hWnd of the parent dialog that you want the OpenDialog to display above.
Post Reply