Working with common dialogs Part1

Published on by Yousfi Benameur


the getfile() function displays the Open dialog box.
it returns the name of the file chosen in the Open dialog box or the empty string if the user closes the Open dialog box by pressing ESC, clicking Cancel or the Close button on the Open dialog box.
this is a usefull function even in vfp9 (very similar to the comDialog one) and its resizable.
its well documented in FoxHelp.
.it selects one item file at once.its available on a level top form even with screen=off.

this codes below in this first part present as follow
   *1* an old method to work with a similar getfile() with a form &listbox (populated with rowsource=7 as files)
       it have one view (as listbox offers) and its resizable.
   *2* GetFileNameFromBrowse function
       its a wrapper of another API (GETOPENFILENAME) but its simplified and easy to use.
   *3* 6 open dialogs made with the vfp2C32 library (compiled as  fll file).(see summary help when run code).
       its very usefull and work with the APIs
           -SHBROWSEFOLDER
           -GETOPENFILENAME
       the work is very simplified by this library.the dialogs are not resizable here.
       can extract code for any of these 6 dialogs for use.Working with APIs is the better solution (no activeX and fully system speed).
Download the library prior at vfpX to make the code working.   
   *4* the commonDialog open dialog box with activeX installed on system.Very light and easy to use.   
   *5* and *6* demonstrates the getfile() capability to work with screen=off even in an exe file.
   


Click on code to select [then copy] -click outside to deselect


*1* An old method to build a getfile dialog box

Publi yform
yform=Newobject("asup")
yform.Show
Read Events
Return
*
Define Class asup As Form
    Top = 0
    Left = 0
    Height = 107
    Width = 363
    ShowWindow = 2
    Caption = "OPEN FILE DIAOG"
    Name = "ymaster"

    Add Object command1 As CommandButton With ;
        Top = 8, ;
        Left = 21, ;
        Height = 25, ;
        Width = 133, ;
        FontBold = .T., ;
        FontSize = 12, ;
        Anchor = 0, ;
        Caption = "getfile...", ;
        MousePointer = 15, ;
        BackColor = Rgb(128,255,0), ;
        Name = "Command1"

    Add Object label1 As Label With ;
        FontBold = .T., ;
        FontSize = 10, ;
        Anchor = 0, ;
        WordWrap = .T., ;
        BackStyle = 0, ;
        Caption = "", ;
        Height = 36, ;
        Left = 12, ;
        Top = 60, ;
        Width = 337, ;
        ForeColor = Rgb(128,0,64), ;
        Name = "Label1"

    Add Object label2 As Label With ;
        AutoSize = .T., ;
        FontBold = .T., ;
        Anchor = 0, ;
        BackStyle = 0, ;
        Caption = "Selected file:", ;
        Height = 17, ;
        Left = 14, ;
        Top = 41, ;
        Width = 75, ;
        ForeColor = Rgb(255,128,0), ;
        Name = "Label2"

    Add Object yhelp1 As yhelp With ;
        visible=.T. , ;
        name="yhelp1"

    Procedure Load
        _Screen.WindowState=1
    Endproc

    Procedure Init
        _Screen.AddProperty("yretval","")
    Endproc

    Procedure Destroy
        Clea Events
    Endproc

    Procedure command1.Click
        Thisform.label1.Caption=""
        *do form old_vfp_getfile
        oo=Newobject("ygetfile")
        oo.Show
        Thisform.label1.Caption=_Screen.yretVAL
    Endproc

Enddefine
*
*-- EndDefine: asup

*****************************
Define Class ygetfile As Form
    Height = 246
    Width = 375
    Desktop = .T.
    ShowWindow = 1
    AutoCenter = .T.
    Caption = "Open file"
    WindowType = 1
    retvalobj = ""
    Name = "Form1"

    Add Object lstfiles As ListBox With ;
        FontBold = .T., ;
        Anchor = 15, ;
        RowSourceType = 7, ;
        Height = 193, ;
        Left = 8, ;
        Top = 12, ;
        Width = 360, ;
        Name = "lstFiles"

    Add Object yfilter As TextBox With ;
        Anchor = 260, ;
        Value = "*.*", ;
        Height = 25, ;
        Left = 24, ;
        Top = 216, ;
        Width = 85, ;
        Name = "yFilter"

    Add Object cmdcancel As CommandButton With ;
        Top = 218, ;
        Left = 204, ;
        Height = 25, ;
        Width = 73, ;
        Anchor = 260, ;
        Caption = "Cancel", ;
        Name = "cmdCancel"

    Add Object cmdopen As CommandButton With ;
        Top = 218, ;
        Left = 288, ;
        Height = 25, ;
        Width = 73, ;
        Anchor = 260, ;
        Caption = "Open", ;
        Name = "cmdOpen"

    Procedure Init
        Lparameters loRetVal
        Local loRetVal
        loRetVal = Createobject('Empty')
        AddProperty(loRetVal, 'FileName', '')

        This.retvalobj=Null
        Thisform.lstfiles.RowSource=Thisform.yfilter.Value
        Thisform.retvalobj = loRetVal
        Return
    Endproc

    Procedure Destroy
        Return Thisform.retvalobj.FileName
    Endproc

    Procedure lstfiles.Valid
        If This.ListIndex > 2
            If Left(This.List[THIS.ListIndex], 1) <> '['
                Thisform.cmdopen.Click
            Endif
        Endif
    Endproc

    Procedure lstfiles.When

        If This.ListIndex > 2
            If Left(This.List[THIS.ListIndex], 1) = '['
                Thisform.cmdopen.Enabled = .F.
            Else
                Thisform.cmdopen.Enabled = .T.
            Endif
        Else
            Thisform.cmdopen.Enabled = .F.
        Endif
    Endproc

    Procedure yfilter.InteractiveChange
        Thisform.lstfiles.RowSource=Thisform.yfilter.Value
        Thisform.Refresh
    Endproc

    Procedure cmdcancel.Click
        _Screen.yretVAL=""
        Thisform.Release
    Endproc

    Procedure cmdopen.Click
        Wait Window "Selected file: " + Thisform.lstfiles.ListItem[THISFORM.lstFiles.ListIndex] Timeout 0.5
        Thisform.retvalobj.FileName = Thisform.lstfiles.ListItem[THISFORM.lstFiles.ListIndex]
        _Screen.yretVAL=Thisform.retvalobj.FileName
        Thisform.Release
    Endproc

Enddefine
*
*-- EndDefine: ygetfile

Define Class yhelp As Label
    AutoSize = .T.
    FontSize = 18
    BackStyle = 0
    Caption = "?"
    Height = 30
    Left = 324
    MousePointer = 15
    Top = 0
    Width = 15
    ForeColor = Rgb(0,255,0)
    Name = "yhelp"

    Procedure Click
        Local m.myvar
        TEXT to m.myvar noshow
this code fires a dialog to open any file on system.
can populate a list box or combo box with the names of files from the current directory.
The list also contains options for you to choose a different drive and directory to display file names from.
The form dialog is modal and return a result to the master form as file chossen.
To populate the control with file names from a directory
Set RowSourceType to 7 (Files).

Set RowSource by specifying a file skeleton or mask, such as *.* or *.fileExt.(set it dynamically in textbox)
For example, the following lines of code set RowSourceType to 7 to indicate that the source type
is files and specifies a file skeleton for RowSource:
Form1.lstfiles.RowSourceType = 7
Form1.lstfiles.RowSource = "*.*"
Dialog form is resizable as wanted.
        ENDTEXT
        Messagebox(m.myvar,0+32+4096,"'Summary help")
    Endproc
Enddefine
*
*-- EndDefine:yhelp


Click on code to select [then copy] -click outside to deselect


*2* 
*An open dialog box with API GetFileNameFromBrowse function
*This function creates an Open dialog box that lets the user specify the drive, directory, and name of a file to open.
*can set a filter for files an box title.the filename dond exceed 255 chars.
*this dialog can work out of vfp screen even in an exe with Screen=off in config.fpw
*getfile() vfp function works inside vfp screen visible only and can block an exe if screen=off.

*!**GetFileNameFromBrowse function
*!*    hwnd[in] Handle to the window that owns the dialog box.
*!*	pszFilePath [in] A null-terminated Unicode string that contains a file name used to initialize the File Name edit control.
*!*	cchFilePath  [in] The number of characters in pszFilePath, including the terminating null character.
*!*	pszWorkingDir [in] The fully-qualified file path of the initial directory.
*!*	pszDefExt [in] A null-terminated Unicode string that contains the default file extension.
*!*	pszFilters [in] A null-terminated Unicode string that defines the filter.
*!*	szTitle [in] A null-terminated Unicode string that is placed in the title bar of the dialog box.


_screen.visible=.f.
Local m.cfilename,m.cpath,m.Ext,m.cFilter,m.ctitle,m.retVal,m.yrep
m.yrep=Addbs(Justpath(Sys(16,1)))   &&starting prg folder

m.cfilename=Space(255)
m.cpath=ysetunicode(m.yrep)
m.cExt=ysetunicode("*.txt")
m.cFilter=ysetunicode("Text files (*.prg)"+Chr(0)+"*.prg"+Chr(0)+"All files (*.*)"+Chr(0)+"*.*"+Chr(0) )
*m.cFilter=ysetUnicode("")
m.ctitle=ysetunicode("GetFileNameFromBrowse API")
m.nBufsize=255

m.nretVAL=ygetfile(cfilename,cpath,cExt,cFilter,ctitle,nBufsize)
_cliptext=m.nretVal
Messagebox("returned:"+Chr(13)+m.nretVAL,0+32+4096,"Result in clipboard",1000)
_screen.visible=.t.



Function ygetfile()
    Lparameters cfilename,cpath,cExt,cFilter,ctitle,bBufsize
    Declare Integer GetFileNameFromBrowse In shell32;
        INTEGER  HWnd,;
        STRING @ pszFilePath,;
        LONG     cchFilePath,;
        STRING   pszWorkingDir,;
        STRING   pszDefExt,;
        STRING   pszFilters,;
        STRING   szTitle

    Declare Integer GetActiveWindow In user32

    Local m.result
    result=GetFileNameFromBrowse(GetActiveWindow(),;
        @cfilename, nBufsize,;
        cpath, cExt, cFilter, ctitle)
    Clea Dlls 'GetFileNameFromBrowse','GetActiveWindow'
    If m.result#0
        Return Strconv(cfilename,6)
    Else
        Return "Cancel!"
    Endi
Endfunc

Function ysetunicode
    Lparameters ystr
    Return  Strconv(ystr+Chr(0),5)
Endfunc

Retu


Click on code to select [then copy] -click outside to deselect


*3* Working with vfp2C32 libray-example adapted from vfp2c32.
*can download it from vfp codeplex version (2.0.0.14 ) at https://vfpx.codeplex.com/releases/view/71594
*must have in this folder the library vfp2c32.fll and vfp2c32.h mandatory to make this code working

#INCLUDE vfp2c.h
clea all
publi m.yrep
    	m.yrep=addbs( justpath(sys(16,1)))
		set defa to (yrep)


publi yform
yform=newObject("ydialogs")
yform.show
read events
retu

*
DEFINE CLASS ydialogs AS form
	BorderStyle = 1
	Top = 0
	Left = 0
	Height = 108
	Width = 345
	ShowWindow = 2
	Caption = "6 dialogsboxes from vfp2C32"
	AlwaysOnTop = .T.
	Name = "Form1"

	ADD OBJECT combo1 AS combobox WITH ;
		Height = 36, ;
		Left = 31, ;
		Top = 29, ;
		Width = 132, ;
		Name = "Combo1"

	ADD OBJECT image1 AS image WITH ;
		Picture = home(1)+"graphics\icons\misc\face03.ico", ;
		Height = 32, ;
		Left = 300, ;
		MousePointer = 15, ;
		Top = 12, ;
		Width = 32, ;
		Name = "Image1"

	PROCEDURE ybuild
		Lparameters ydiag
		If Pcount()=0 Or !Between(ydiag,1,6)    &&&6 dialog boxes
		    Return .F.
		Endi

		#Define CDN_FIRST			-601
		#Define CDN_LAST			-699
		#Define CDN_INITDONE		-601
		#Define CDN_SELCHANGE		-602
		#Define CDN_FOLDERCHANGE	-603
		#Define CDN_SHAREVIOLATION	-604
		#Define CDN_HELP			-605
		#Define CDN_FILEOK			-606
		#Define CDN_TYPECHANGE		-607
		#Define CDN_INCLUDEITEM		-608

		#Define CDM_FIRST			0x464
		#Define CDM_LAST			0x4C8
		#Define CDM_GETSPEC			0x464
		#Define CDM_GETFILEPATH		0x465
		#Define CDM_GETFOLDERPATH	0x466
		#Define CDM_GETFOLDERIDLIST	0x467
		#Define CDM_SETCONTROLTEXT	0x468
		#Define CDM_HIDECONTROL		0x469
		#Define CDM_SETDEFEXT		0x470

		#Define IDOK				1
		#Define IDCANCEL			2

		Local lcFolder
		lcFolder=""

		Do Case

		    Case ydiag=1
		        If SHBROWSEFOLDER('Choose a Folder',0,@lcFolder)
		            Messagebox("Folder"+ lcFolder,0+32+406,"",1200)
		        Else
		            Messagebox("Dialog aborted",0+32+406,"",1200)
		        Endif

		    Case ydiag=2
    try   &&sometime an error occurs as exception !
   =SHBROWSEFOLDER('Choose a Folder',0,@lcFolder,"C:\Users")
   catch
   messagebox("An error was occured",16+4096,'',1000)
   endtry

		    Case ydiag=3
		        =SHBROWSEFOLDER('Choose yet another Folder :)',0,@lcFolder,'','BrowseFolderCallback')


		    Case ydiag=4
		        && like standard GETFILE, but without places bar
		        Local lcFile
		        lcFile = GETOPENFILENAME(0,"All Files" + Chr(0) + "*.*","","C:","Custom Title",OFN_EX_NOPLACESBAR)
		        Do Case
		            Case Vartype(lcFile) = 'C'
		                Messagebox( "File" + lcFile + " selected",0+32+4096,'',1200)
		            Case lcFile = 0
		                Messagebox( "Dialog box aborted",0+32+4096,'',1200)
		            Case lcFile = -1
		                Messagebox( "Error in dialog box.",0+32+4096,'',1200)
		        Endcase

		    Case ydiag=5
		        && multiselect GETFILE, by passing an arrayname in the 7th parameter
		        && always returns a numeric value !!
		        lnFiles = GETOPENFILENAME(0,"All Files" + Chr(0) + "*.*","","C:","Multiselect Example",0,"laFiles")
		        Do Case
		            Case lnFiles = -1
		                AERROREX('laError')
		                Display Memory Like laError
		            Case lnFiles = 0
		                Messagebox( "Dialog box aborted",0+32+4096,'',1200)
		            Otherwise
		                && Path is in laFiles[1], all other elements contain a filename (without the path)
		                Display Memory Like laFiles
		        Endcase

		    Case ydiag=6
		        && use of a callback function to respond to events inside the dialog
		        lnFiles = GETOPENFILENAME(0,"Special bat Files" + Chr(0) + "*.bat","","C:","",0,"","OpenFileCallback")
		        Do Case
		            Case Vartype(lnFiles) = 'C'
		                Messagebox( "File" + lnFiles + " selected",0+32+4096,'',1200)
		            Case lnFiles = 0
		                Messagebox( "Dialog box aborted",0+32+4096,'',1200)
		            Case lnFiles = -1
		                AERROREX('laError')
		                Display Memory Like laError
		        Endcase
		Endcase
		Retu
	ENDPROC


	PROCEDURE browsefoldercallback
		lparameters lnHwnd, uMsg, lParam
			messagebox(trans(lnHwnd)+chr(13)+ trans(uMsg)+chr(13)+ trans(lParam),0+32+406,'',1200)
	ENDPROC


	PROCEDURE openfilecallback
		lparameters lnHwnd, lnControlID, lnCode
			IF lnCode = CDN_INITDONE
				&& in this event the appearance of the dialog can be customized
				&& center the window in it's parent window
				CenterWindowEx(lnHwnd)
				&& change button captions
				DECLARE INTEGER SendMessage IN user32.dll AS SendMessageString INTEGER, INTEGER, INTEGER, STRING
				SendMessageString(lnHwnd,CDM_SETCONTROLTEXT,IDOK,"Choose")
				SendMessageString(lnHwnd,CDM_SETCONTROLTEXT,IDCANCEL,"Cancel")
				&& for more examples google for "GetOpenFileName" and you'll find a bunch of articles/examples.
				&& Most of them for Visual Basic, but they can be easily translated to VFP.
			ENDIF
			RETURN 0 && the function must return an integer or logical value
	ENDPROC

	PROCEDURE Destroy
		set library to
		clea events
	ENDPROC

	PROCEDURE Init
		
		SET LIBRARY TO locfile("vfp2c32.fll") ADDITIVE
		*INITVFP2C32(VFP2C_INIT_ALL)
	ENDPROC

	PROCEDURE combo1.Init
		with this
		for i=1 to 6
		.additem("Dialog"+trans(i))
		endfor
		.listindex=1
		.value=1
		.style=2
		endwith
	ENDPROC

	PROCEDURE combo1.Click
		thisform.ybuild(this.value)
	ENDPROC

	PROCEDURE image1.Click
		local m.myvar
		text to m.myvar noshow
VFP2C32 (acronym for "VFP to C 32 bit") is a bridge between Visual Foxpro and the C programming language.
Additionally it contains wrappers around many windows api functions.

With this library you're able to create any C datatype - structs, unions, arrays - from within VFP.
The creation of wrapper classes for C struct or union types is explained in the topic VFP2C32Front.
C arrays can be created with the classes in the vfp2carray.prg file.
The windows api wrappers allows you to use a wide range of functionality build into windows.
A registry api, querying printer information and controlling windows services
Note :these 6 dialogs are not resizable.
      dialog position is not controlable

		endtext

		MESSAGEBOXEX(m.myvar, 0, 'Dialogs from vfp2C32 library 1-6', _VFP.hWnd, 102, VFP2CSYS(1))
	ENDPROC

ENDDEFINE
*
*-- EndDefine: ydialogs


Click on code to select [then copy] -click outside to deselect


*4* a commondialog open with an (activeX) OCX "mscomdlg.commondialog" present in system library microsof commondialog SP6.

Local  loComDialog, lcFileName
Try
    loComDialog = Newobject( "mscomdlg.commondialog" )
Catch
    Messagebox("mscomdlg.commondialog is not installed",16+4096)
Endtry

* Set filters example
loComDialog.Filter = "All Files (*.*)|*.*|Prg Files(*.PRG)| *.prg|Scx Files(*.scx)| *.scx|Text Files(*.txt)|*.txt|Batch Files (*.bat)|*.bat"
* Specify default filter
loComDialog.FilterIndex = 2
loComDialog.MaxFileSize = 260 &&  without this you get: OLE IDispatch exception code 0 from CommonDialog

* Display the Open dialog box
loComDialog.ShowOpen()
* Get File Name
lcFileName = loComDialog.FileName

If ! Empty(lcFileName)
    Messagebox( lcFileName,0+32+4096,'',1200 )
Else
    Messagebox( 'Canceled' ,0+32+4096,'',1200 )
Endi


Working with common dialogs  Part1
Working with common dialogs  Part1
Working with common dialogs  Part1
Working with common dialogs  Part1

Click on code to select [then copy] -click outside to deselect


*5* DEMONSTRATE THE GETFILE() DIALOG AVAILABLE ON A TOP LEVEL FORM AND SCREEN=OFF

Publi yform
yform=Newobject("asup")
yform.Show
Read Events
Return
*
Define Class asup As Form
    Top = 28
    Left = 142
    Height = 75
    Width = 354
    ShowWindow = 2
    Caption = "Form1"
    Name = "Form1"

    Add Object command1 As CommandButton With ;
        AutoSize = .T., ;
        Top = 12, ;
        Left = 24, ;
        Height = 34, ;
        Width = 290, ;
        FontSize = 12, ;
        Caption = "Getfile with top level form & screen=off", ;
        Name = "Command1"

    Procedure Load
        _Screen.Visible=.F.
    Endproc

    Procedure command1.Click
        x=Getfile()
        messagebox("choosen file:"+m.x,0+32+406,'',1200)
        _Screen.Visible=.T.
    Endproc

    Procedure Destroy
        Clea Events
    Endproc

Enddefine
*
*-- EndDefine: asup



Click on code to select [then copy] -click outside to deselect


*6*
*getfile() works as well if the screen=off and even in an exe

_screen.visible=.f.
i=0
t0=seconds()
do while seconds()-t0<=4   &&preventive way!
if i=0
x=getfile()
i=i+1
endi
enddo
messagebox("Choosen file:"+chr(13)+m.x,0+32+4096,'',1200)
_screen.visible=.t.
return


Working with common dialogs  Part1
To be informed of the latest articles, subscribe:
Comment on this post