Skip to content

Latest commit

 

History

History
226 lines (181 loc) · 6.87 KB

sample_265.md

File metadata and controls

226 lines (181 loc) · 6.87 KB

Home

Creating the Save dialog box to specify the drive, directory, and name of a file to save

Before you begin:

See also:


Code:

DO decl

* some of the bit flags for the dialog
#DEFINE OFN_HIDEREADONLY 4
#DEFINE OFN_NOCHANGEDIR 8
#DEFINE OFN_EXTENSIONDIFFERENT 0x400
#DEFINE OFN_PATHMUSTEXIST 0x800
#DEFINE OFN_CREATEPROMPT 0x2000
#DEFINE OFN_EXPLORER 0x80000
#DEFINE OFN_DONTADDTORECENT 0x2000000

*| typedef struct tagOFN {
*|   DWORD         lStructSize;      0:4
*|   HWND          hwndOwner;        4:4
*|   HINSTANCE     hInstance;        8:4
*|   LPCTSTR       lpstrFilter;     12:4
*|   LPTSTR        lpstrCustFilt;   16:4
*|   DWORD         nMaxCustFilter;  20:4
*|   DWORD         nFilterIndex;    24:4
*|   LPTSTR        lpstrFile;       28:4
*|   DWORD         nMaxFile;        32:4
*|   LPTSTR        lpstrFileTitle;  36:4
*|   DWORD         nMaxFileTitle;   40:4
*|   LPCTSTR       lpstrInitialDir; 44:4
*|   LPCTSTR       lpstrTitle;      48:4
*|   DWORD         Flags;           52:4
*|   WORD          nFileOffset;     56:2
*|   WORD          nFileExtension;  58:2
*|   LPCTSTR       lpstrDefExt;     60:4
*|   LPARAM        lCustData;       64:4
*|   LPOFNHOOKPROC lpfnHook;        68:4
*|   LPCTSTR       lpTemplateName;  72:4 = 76 bytes
*| #if (_WIN32_WINNT >= 0x0500)
*|   void *        pvReserved;      76:4
*|   DWORD         dwReserved;      80:4
*|   DWORD         FlagsEx;         84:4
*| #endif // (_WIN32_WINNT >= 0x0500)
*| } OPENFILENAME, *LPOPENFILENAME; total = 88 bytes

#DEFINE OPENFILENAME_SIZE  76  && set to 88 for W2K

LOCAL lcBuffer, loFilter, loFilename, loFilenameRet,;
	loTitlebar, loDefExt, lnFlags, lnFileOffset, lnExtOffset,;
	lcFullname, lcPath, lcFilename, lcFileext

loFilter = CreateObject("PChar",;
	"Text Files" + Chr(0) + "*.txt;*.bak" + Chr(0)+Chr(0))

loFilename = CreateObject("PChar", Padr("myfile.txt", 250,Chr(0)))

loFilenameRet = CreateObject("PChar", Repli(Chr(0),250))

loTitlebar = CreateObject("PChar",;
	"Will you save this file at least?")

loDefExt = CreateObject("PChar", "TXT")

lnFlags = OFN_PATHMUSTEXIST + OFN_EXTENSIONDIFFERENT +;
	OFN_CREATEPROMPT + OFN_HIDEREADONLY + OFN_NOCHANGEDIR

* compiling the OPENFILENAME structure
* Rem: initdir - default chosen

lcBuffer = num2dword(OPENFILENAME_SIZE) +;
	num2dword(GetActiveWindow()) +;
	num2dword(0) +;
	num2dword(loFilter.GetAddr()) +;
	num2dword(0) +;
	num2dword(0) +;
	num2dword(1) +;
	num2dword(loFilename.GetAddr()) +;
	num2dword(loFilename.GetAllocSize()) +;
	num2dword(loFilenameRet.GetAddr()) +;
	num2dword(loFilenameRet.GetAllocSize()) +;
	num2dword(0) +;
	num2dword(loTitlebar.GetAddr()) +;
	num2dword(lnFlags) +;
	num2dword(0) +;
	num2dword(loDefExt.GetAddr()) +;
	num2dword(0) +;
	num2dword(0) +;
	num2dword(0)

* creating a Save dialog box using the prepared structure

IF GetSaveFileName (@lcBuffer) = 0
	LOCAL lnErrorCode
	lnErrorCode = CommDlgExtendedError()
	IF lnErrorCode <> 0
		? "Error code:", lnErrorCode
	ELSE
	* the Cancel button selected
	ENDIF

ELSE
	lcFullname = STRTRAN(Trim(loFilename.GetValue()), Chr(0),"")
	lcFilename = STRTRAN(Trim(loFilenameRet.GetValue()), Chr(0),"")

	lnFileOffset = buf2word(SUBSTR(lcBuffer, 57,2))
	lnExtOffset = buf2word(SUBSTR(lcBuffer, 59,2))

	lcPath = SUBSTR(lcFullname, 1, lnFileOffset-1)
	lcFileext = SUBSTR(lcFullname, lnExtOffset+1)

	? lcFullname
	? lcPath
	? lcFilename
	? lcFileext
ENDIF
* end of main

FUNCTION  num2dword (lnValue)
#DEFINE m0       256
#DEFINE m1     65536
#DEFINE m2  16777216
	LOCAL b0, b1, b2, b3
	b3 = Int(lnValue/m2)
	b2 = Int((lnValue - b3*m2)/m1)
	b1 = Int((lnValue - b3*m2 - b2*m1)/m0)
	b0 = Mod(lnValue, m0)
RETURN Chr(b0)+Chr(b1)+Chr(b2)+Chr(b3)

FUNCTION  buf2word (lcBuffer)
RETURN Asc(SUBSTR(lcBuffer, 1,1)) + ;
	Asc(SUBSTR(lcBuffer, 2,1)) * 256

DEFINE CLASS PChar As Custom
	PROTECTED hMem

PROCEDURE  Init (lcString)
	THIS.hMem = 0
	THIS.setValue (lcString)

PROCEDURE  Destroy
	THIS.ReleaseString

FUNCTION getAddr  && returns a pointer to the string
RETURN THIS.hMem

FUNCTION getValue && returns string value
	LOCAL lnSize, lcBuffer
	lnSize = THIS.getAllocSize()
	lcBuffer = SPACE(lnSize)

	IF THIS.hMem <> 0
		DECLARE RtlMoveMemory IN kernel32 As Heap2Str;
			STRING @, INTEGER, INTEGER
		= Heap2Str (@lcBuffer, THIS.hMem, lnSize)
	ENDIF
RETURN lcBuffer

FUNCTION getAllocSize  && returns allocated memory size (string length)
	DECLARE INTEGER GlobalSize IN kernel32 INTEGER hMem
RETURN Iif(THIS.hMem=0, 0, GlobalSize(THIS.hMem))

PROCEDURE setValue (lcString) && assigns new string value
#DEFINE GMEM_FIXED   0
	THIS.ReleaseString

	DECLARE INTEGER GlobalAlloc IN kernel32 INTEGER, INTEGER
	DECLARE RtlMoveMemory IN kernel32 As Str2Heap;
		INTEGER, STRING @, INTEGER

	LOCAL lnSize
	lcString = lcString + Chr(0)
	lnSize = Len(lcString)
	THIS.hMem = GlobalAlloc (GMEM_FIXED, lnSize)
	IF THIS.hMem <> 0
		= Str2Heap (THIS.hMem, @lcString, lnSize)
	ENDIF

PROCEDURE ReleaseString  && releases allocated memory
	IF THIS.hMem <> 0
		DECLARE INTEGER GlobalFree IN kernel32 INTEGER
		= GlobalFree (THIS.hMem)
		THIS.hMem = 0
	ENDIF
ENDDEFINE

PROCEDURE  decl
	DECLARE INTEGER GetActiveWindow IN user32
	DECLARE INTEGER GlobalFree IN kernel32 INTEGER hMem
	DECLARE INTEGER GetSaveFileName IN comdlg32 STRING @lpofn
	DECLARE INTEGER CommDlgExtendedError IN comdlg32  

Listed functions:

CommDlgExtendedError
GetActiveWindow
GetSaveFileName
GlobalAlloc
GlobalFree
GlobalSize

Comment:

The OPENFILENAME structure length depends on the OS, and can be 76 or 88 bytes.

This is important, because invalid parameter creates an error. Note that this structure is used with GetOpenFileName and GetSaveFileName functions. There is substantial set of OFN flags to control the dialog behaviour.

To fill the OPENFILENAME structure -- as well as almost all other Comdlg structures used -- you need not just strings but pointers to strings. There is a class PChar in this examples, which creates such extended strings. In more simple cases the StrDup is quite enough to accomplish this task.