Skip to content

Instantly share code, notes, and snippets.

@MarkGoldberg
Created November 3, 2016 12:04
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Embed
What would you like to do?
GetSaveFileName API wrapped for Clarion for Windows

Pardon the messy code, I have not cleaned this at all as it seemed to me that if you encounter problems that some of my ancient notes etc. might be handy

Example call: if MySaveFileName('Save Image As...', rou:sFileName_DriveDir, rou:sFileName_BaseName,'PNG-portable network graphics (recommended)|.PNG|Bitmap|.BMP|JPEG|.JPG|TIFF|.TIF|Encapsulated Post Script|.EPS|RGB|.RBG')

Note about FileSaveName.CLW

  • I notice it has a MEMBER statement Clearly that will need to be cleaned up. So, WHY does it have one? the calls to MG.BaseName and MG.DriveDir I'd replace those with calls into https://github.com/MarkGoldberg/CwUnit/blob/master/Libsrc/ctFileHelper.inc https://github.com/MarkGoldberg/CwUnit/blob/master/Libsrc/ctFileHelper.clw

  • There are ASSERT(0,eqDBG & 'sometext')
    these are calls to OutputDebugString in my system just rem those out.

  • There are calls into oGLO.INI_Non_Pos these are INI retrieve/save calls but here's the thing, when I search my code, I never use those outside of MySaveFileName, so it only makes sense if you only make one call into this procedure which, as it turns out, it how I'm using it. again, this is poor design

  • lcl.DefaultExt = 'BMP' appears to be hard coded into the procedure this is just poor either the default EXT should be a parameter, or everything should be wrapped in a class, and DefaultExt should be made a property and side-effected in that way.

compile('***',_WIDTH32_)
ANSI EQUATE('A')
***
omit ('***',_WIDTH32_)
ANSI EQUATE('')
***
!-Rely On Once due to IDE Navigation Bugs-! omit('*** ifdef API_CommonDialog ***',ifDef_API_CommonDialog)
!-Rely On Once due to IDE Navigation Bugs-!ifDef_API_CommonDialog EQUATE(1)
INCLUDE('winequ.clw'),ONCE
INCLUDE('equates.clw'),ONCE
LPCTSTR EQUATE(ULONG) !A 32-bit pointer to a constant character string that is portable for Unicode and DBCS.
LPTSTR EQUATE(ULONG) !A 32-bit pointer to a character string that is portable for Unicode and DBCS.
WORD EQUATE(uShort) !<--- was declared as a Signed, but signed becomes a ULONG in 32 bit
!<--- had to be re-declard, otherwise would get CDERR_STRUCTSIZE errors
INTCPP EQUATE(Signed) !Can't call it INT as this conflicts with the int() function !moved here 1/8/99
!!! API_CommonDialog::LinkClass class,type,module('API_CommonDialog'),link('API_CommonDialog')
!!! end
omit('EndDefine',_WINAPI_) !<--see svapi.inc
NMHDR Group,Type !typedef struct tagNMHDR {
hwndFrom HWND
idFrom UINT
!code UINT
TheCode UINT !MG: Modification to avoid CW reserved word
end !} NMHDR;
!END-omit('EndDefine',_WINAPI_) !<--see svapi.inc
OFNotify group,type !typedef struct _OFNOTIFY { // on
hdr LIKE(NMHDR)
lpOFN LPVOID !LPOPENFILENAME
pszFile LPTSTR !// May be NULL
end !} OFNOTIFY, FAR *LPOFNOTIFY;
!see commdlg.h
OpenFileName Group,Type !typedef struct tagOFN { // ofn
lStructSize DWORD
hwndOwner HWND
hInstance HINSTANCE
lpstrFilter LPCTSTR
lpstrCustomFilter LPTSTR
nMaxCustFilter DWORD
nFilterIndex DWORD
lpstrFile LPTSTR
nMaxFile DWORD
lpstrFileTitle LPTSTR
nMaxFileTitle DWORD
lpstrInitialDir LPCTSTR
lpstrTitle LPCTSTR
Flags DWORD
nFileOffset WORD
nFileExtension WORD
lpstrDefExt LPCTSTR
lCustData DWORD
lpfnHook LPVOID !LPOFNHOOKPROC
lpTemplateName LPCTSTR
end
OFN_READONLY EQUATE(00000001h)
OFN_OVERWRITEPROMPT EQUATE(00000002h)
OFN_HIDEREADONLY EQUATE(00000004h)
OFN_NOCHANGEDIR EQUATE(00000008h)
OFN_SHOWHELP EQUATE(00000010h)
OFN_ENABLEHOOK EQUATE(00000020h)
OFN_ENABLETEMPLATE EQUATE(00000040h)
OFN_ENABLETEMPLATEHANDLE EQUATE(00000080h)
OFN_NOVALIDATE EQUATE(00000100h)
OFN_ALLOWMULTISELECT EQUATE(00000200h)
OFN_EXTENSIONDIFFERENT EQUATE(00000400h)
OFN_PATHMUSTEXIST EQUATE(00000800h)
OFN_FILEMUSTEXIST EQUATE(00001000h)
OFN_CREATEPROMPT EQUATE(00002000h)
OFN_SHAREAWARE EQUATE(00004000h)
OFN_NOREADONLYRETURN EQUATE(00008000h)
OFN_NOTESTFILECREATE EQUATE(00010000h)
OFN_NONETWORKBUTTON EQUATE(00020000h)
OFN_NOLONGNAMES EQUATE(00040000h) !// force no long names for 4.x modulesh)
!#if(WINVER >= 0x0400)
OFN_EXPLORER EQUATE(00080000h) !// new look commdlgh)
OFN_NODEREFERENCELINKS EQUATE(00100000h)
OFN_LONGNAMES EQUATE(00200000h) !// force long names for 3.x modulesh)
!#endif /* WINVER >= 0x0400 */
!#if(WINVER >= 0x0500)
OFN_ENABLESIZING EQUATE(000800000h) !<-- retrieved from a non-english website, probably correct...
!================================================================== see CDErr.h
!---------- The following general error codes can be returned for any of the common dialog box functions
CDERR_DIALOGFAILURE EQUATE(0FFFFh)
CDERR_GENERALCODES EQUATE(00000h)
CDERR_STRUCTSIZE EQUATE(00001h)
CDERR_INITIALIZATION EQUATE(00002h)
CDERR_NOTEMPLATE EQUATE(00003h)
CDERR_NOHINSTANCE EQUATE(00004h)
CDERR_LOADSTRFAILURE EQUATE(00005h)
CDERR_FINDRESFAILURE EQUATE(00006h)
CDERR_LOADRESFAILURE EQUATE(00007h)
CDERR_LOCKRESFAILURE EQUATE(00008h)
CDERR_MEMALLOCFAILURE EQUATE(00009h)
CDERR_MEMLOCKFAILURE EQUATE(0000Ah)
CDERR_NOHOOK EQUATE(0000Bh)
CDERR_REGISTERMSGFAIL EQUATE(0000Ch)
!------------ The following error codes can be returned for the PrintDlg function:
PDERR_PRINTERCODES EQUATE(01000h)
PDERR_SETUPFAILURE EQUATE(01001h)
PDERR_PARSEFAILURE EQUATE(01002h)
PDERR_RETDEFFAILURE EQUATE(01003h)
PDERR_LOADDRVFAILURE EQUATE(01004h)
PDERR_GETDEVMODEFAIL EQUATE(01005h)
PDERR_INITFAILURE EQUATE(01006h)
PDERR_NODEVICES EQUATE(01007h)
PDERR_NODEFAULTPRN EQUATE(01008h)
PDERR_DNDMMISMATCH EQUATE(01009h)
PDERR_CREATEICFAILURE EQUATE(0100Ah)
PDERR_PRINTERNOTFOUND EQUATE(0100Bh)
PDERR_DEFAULTDIFFERENT EQUATE(0100Ch)
!------------- The following error codes can be returned for the ChooseFont function:
CFERR_CHOOSEFONTCODES EQUATE(02000h)
CFERR_NOFONTS EQUATE(02001h)
CFERR_MAXLESSTHANMIN EQUATE(02002h)
!------------- The following error codes can be returned for the GetOpenFileName and GetSaveFileName functions:
FNERR_FILENAMECODES equate(03000h) !MG: not in my MSDN
FNERR_SUBCLASSFAILURE equate(03001h)
FNERR_INVALIDFILENAME equate(03002h)
FNERR_BUFFERTOOSMALL equate(03003h)
!------------- The following error code can be returned for the FindText and ReplaceText functions:
FRERR_FINDREPLACECODES equate(04000h)
FRERR_BUFFERLENGTHZERO equate(04001h) !FindText and ReplaceText
!------------- MG: assumed to be for ChoseColor
CCERR_CHOOSECOLORCODES equate(05000h) !MG: Not in my MSDN
!================================================================== see CDErr.h -end
WM_NOTIFY EQUATE(004Eh) !#if(WINVER >= 0x0400)
WM_INITDIALOG EQUATE(0110h)
WM_USER EQUATE(Event:User) !0400H)
WM_NULL EQUATE(0000h)
WM_CREATE EQUATE(0001h)
WM_DESTROY EQUATE(0002h)
WM_MOVE EQUATE(0003h)
!WM_SIZE EQUATE(0005h)
WM_ACTIVATE EQUATE(0006h)
!// WM_ACTIVATE state values
WA_INACTIVE EQUATE(0)
WA_ACTIVE EQUATE(1)
WA_CLICKACTIVE EQUATE(2)
WM_SETFOCUS EQUATE(0007h)
WM_KILLFOCUS EQUATE(0008h)
WM_ENABLE EQUATE(000Ah)
WM_SETREDRAW EQUATE(000Bh)
WM_SETTEXT EQUATE(000Ch)
WM_GETTEXT EQUATE(000Dh)
WM_GETTEXTLENGTH EQUATE(000Eh)
WM_PAINT EQUATE(000Fh)
WM_CLOSE EQUATE(0010h)
!WM_QUERYENDSESSION EQUATE(0011h)
WM_QUIT EQUATE(0012h)
WM_QUERYOPEN EQUATE(0013h)
WM_ERASEBKGND EQUATE(0014h)
WM_SYSCOLORCHANGE EQUATE(0015h)
!WM_ENDSESSION EQUATE(0016h)
WM_SHOWWINDOW EQUATE(0018h)
WM_WININICHANGE EQUATE(001Ah)
!see commdlg.h
CDM_FIRST EQUATE(WM_USER + 100)
CDM_LAST EQUATE(WM_USER + 200)
Itemize,pre
CDM_GETSPEC EQUATE(CDM_FIRST) !Retrieves the filename (not including the path) of the file currently selected in the dialog box.
CDM_GETFILEPATH EQUATE !Retrieves the path and filename of the selected file.
CDM_GETFOLDERPATH EQUATE !Retrieves the path of the current folder or directory for the dialog box.
CDM_GETFOLDERIDLIST EQUATE !Retrieves the item identifier list corresponding to the current folder that the dialog box has open. For more information about item identifier lists, seeItem Identifiers and Identifier Lists.
CDM_SETCONTROLTEXT EQUATE !Sets the text in the specified control.
CDM_HIDECONTROL EQUATE !Hides the specified control.
CDM_SETDEFEXT EQUATE !Sets the default filename extension for the dialog box.
end
!// Return values for the registered message sent to the hook function
!// when a sharing violation occurs. OFN_SHAREFALLTHROUGH allows the
!// filename to be accepted, OFN_SHARENOWARN rejects the name but puts
!// up no warning (returned when the app has already put up a warning
!// message), and OFN_SHAREWARN puts up the default warning message
!// for sharing violations.
!//
!// Note: Undefined return values map to OFN_SHAREWARN, but are
!// reserved for future use.
OFN_SHAREFALLTHROUGH EQUATE(2)
OFN_SHARENOWARN EQUATE(1)
OFN_SHAREWARN EQUATE(0)
!from commdlg.h !123456789-123456789-123456789-
!------------- these registered messages have been superceeded
LBSELCHSTRING EQUATE('commdlg_LBSelChangedNotify')
SHAREVISTRING EQUATE('commdlg_ShareViolation' )
FILEOKSTRING EQUATE('commdlg_FileNameOK' )
COLOROKSTRING EQUATE('commdlg_ColorOK' )
SETRGBSTRING EQUATE('commdlg_SetRGBColor' )
HELPMSGSTRING EQUATE('commdlg_help' )
FINDMSGSTRING EQUATE('commdlg_FindReplace' )
!// HIWORD values for lParam of commdlg_LBSelChangeNotify message
CD_LBSELNOITEMS EQUATE(-1)
CD_LBSELCHANGE EQUATE( 0)
CD_LBSELSUB EQUATE( 1)
CD_LBSELADD EQUATE( 2)
!// Get/SetWindowWord/Long offsets for use with WC_DIALOG windows
DWL_MSGRESULT equate(0)
DWL_DLGPROC equate(4)
DWL_USER equate(8)
!MGCustData Group,type
!FilePath cSTRING(MAX_PATH)
!FileSelected cSTRING(MAX_PATH)
! end
map
module('api')
GetOpenFileName(*OpenFileName),bool,pascal,raw,name('GetOpenFileName' & ANSI)
GetSaveFileName(*OpenFileName),bool,pascal,raw,name('GetSaveFileName' & ANSI)
CommDlgExtendedError(),DWORD,name('CommDlgExtendedError')
!GetFileTitle(LPCSTR, LPSTR, WORD),Short,pascal,raw,name('GetFileTitle' & ANSI)
!--- problem as defined already...
SendMessage (HWND hWnd, | // Handle of destination window
UINT Msg, | // Message to send
WPARAM wParam, | // First message parameter
LPARAM lParam |); // Second message parameter
),LRESULT,pascal,raw,name('SendMessage' & ANSI),proc
!RegisterWindowMessage(LPCTSTR lpString),UINT,raw,pascal,name('RegisterWindowMessage' & ANSI) !GetLastError if returns 0 (should return between C000h - FFFFh)
RegisterWindowMessage(const *Cstring lpString),UINT,raw,pascal,name('RegisterWindowMessage' & ANSI) !GetLastError if returns 0 (should return between C000h - FFFFh)
!--- problem as defined already...
SetWindowLong (HWND hWnd, | // handle of window
intCPP nIndex, | // offset of value to set
LONG dwNewLong | // new value
),LONG,Pascal,Raw,Name('SetWindowLong' & ANSI),Proc
GetWindowLong(HWND hWnd, intCPP nIndex),LONG,Pascal,Raw,Name('GetWindowLong' & ANSI) !// nIndex = offset of value to retrieve (see GWL_* and DWL_* equates)
!The GetDlgItemText function retrieves the title or text associated with a control in a dialog box.
GetDlgItemText(HWND hDlg ,| // handle of dialog box
intCPP nIDDlgItem ,| // identifier of control
LPTSTR lpString ,| // address of buffer for text
intCPP nMaxCount | // maximum size of string
),Uint,Pascal,Raw,name('GetDlgItemText' & ANSI),proc !GetLastError if returns 0 (should return Num chars in buffer)
memcpy(long lpDest, long lpSource, long nCount),long,proc,name('_memcpy')
end
end
!end-omit('*** ifdef API_CommonDialog ***',ifDef_API_CommonDialog)
!Region Documentation
! ===================================================================================
! -------------------------------------------------------------------------------------
! This include file:
! Created: 5/16/02 by Mark Goldberg of Monolith Custom Computing, Inc.
! Mark@MonolithCC.com
! Updates:
! -------------------------------------------------------------------------------------
!
!
!
!
! see MSDN98\98VSa\1033 for the following information
!
!On page 375, in the documentation for the lpstrCustomFilter member of the OPENFILENAME data structure, add a comment to indicate that an application can use the lpstrCustomFilter member to specify one additional filter. The description of this member incorrectly states that "The system copies the strings to the buffer when the user chooses the OK button to close the dialog box." This statement should say that the system copies the last-selected search filter from the List Files As Type combo box into the buffer to which this member points. The online Help file contains additional text (not present in the printed manual) that correctly describes this process.
!
!On page 376, in the documentation for the lpstrFile member, add a comment to note that this member takes precedence over the lpstrCustomFilter member. In other words, if lpstrFile is not blank, the File Name edit control shows its contents.
!
!On page 376, the documentation for the lpstrInitialDir member contains the following statement: "If the lpstrFile member contains a string that specifies a valid path, the common dialog box procedure will use the path specified by this string instead of the path specified by the string to which lpstrInitialDir points." To eliminate any confusion, replace the phrase "this string" with "the lpstrFile string."
!
!On page 378, in the documentation for the OFN_NOCHANGEDIR flag, change its documentation to state that this flag forces the dialog box to change to the current directory. The common Open dialog box procedure stores the current directory when it processes the WM_INITDIALOG message and restores the current directory when the dialog box exits.
!
!On page 394, in the documentation for the hDevMode and hDevNames members of the PRINTDLG structure, add a comment to indicate that the application that calls the PrintDlg function must call GlobalFree() to free the memory associated with these handles.
!
!On page 395, add a comment to the documentation for the hDC member to indicate that the application must call the DeleteDC function in order to free the device context specified in this member.
!
!
!see DDX (Dialog Data Exchange)
!see DDV (Dialog Data Validation)
!see "Common Dialog Messages" for Registered Messages
!see "Customizing Common Dialog Boxes"
!see "Using the Common Dialogs Under Windows 95"
!
!
!!from resource.h in comdlg32.c example, I`ve pasted this here for the IDE_PATH and IDE_SELECT info
!!however I'm not convinced that these values are correct.
!#define IDD_COMDLG32 100
!#define IDE_PATH 102
!#define IDM_FILEOPEN 106
!#define IDM_EXIT 107
!#define IDM_ABOUT 108
!#define IDD_ABOUT 113
!#define IDE_SELECTED 1022
!#define IDC_STATIC -1
!
! ===================================================================================
!EndRegion Documentation
MEMBER('b4')
INCLUDE('API_CommonDialog.inc'),ONCE !has map
!INCLUDE('FileSaveName.inc'),ONCE
MySaveFileName PROCEDURE(STRING xTitle, *STRING xInOutDriveDir ,*STRING xInOutFileName, STRING xExtensions)!,bool,proc
HoldPath STRING(FILE:MaxFilePath),AUTO
RetFilePicked BOOL,AUTO
CODE
HoldPath = LONGPATH()
SETPATH( xInOutDriveDir )
xInOutFileName = MG.BaseName( xInOutFileName )
RetFilePicked = MySaveFileName( xTitle, xInOutFileName, xExtensions )
IF RetFilePicked
Assert(0,eqDBG&'MySaveFileName FileName['& xInOutFileName &'] (just after call)')
xInOutDriveDir = MG.DriveDir( xInOutFileName ) ;Assert(0,eqDBG&'MySaveFileName DriveDir['& xInOutDriveDir &']')
xInOutFileName = MG.BaseName( xInOutFileName ) ;Assert(0,eqDBG&'MySaveFileName FileName['& xInOutFileName &']')
END
SETPATH( HoldPath )
RETURN RetFilePicked
!=============================================================================================
MySaveFileName PROCEDURE(STRING xTitle, *STRING xInOutFileName, STRING xExtensions)
!argExtensions should match CW style extensions
!Testing: 5/17/02: on KMH Win98se box, if delete (all graphics) then cancel, then Save Again, it changes the folder to MyDocuments
argNum Itemize,pre(argNum:)
Title EQUATE(1)
FileName EQUATE
Extensions EQUATE
end
! FileDialog([title],file[,extensions][,flag])
lcl group
MyOFN LIKE(OpenFileName)
RetVal Bool
Extensions cSTRING(255) !<-- poor technique
FileName cSTRING(FILE:MaxFilePath + 1) !<-- too small if supporting OFN_ALLOWMULTISELECT
BaseName cSTRING(FILE:MaxFileName + 1)
DialogTitle cSTRING(255)
DefaExt cSTRING(14) !MSDN says "This string can be any length, but only the first three characters are appended" testing (on Win2K) shows otherwise (wanted to make sure for trailing null <0>
OutDefaExt cSTRING(14)
!MyMGCustData LIKE(MGCustData)
ExtErr DWORD
OutFileName cSTRING(FILE:MaxFilePath + 1)
OutPathName cSTRING(FILE:MaxFilePath + 1)
OutBaseName cSTRING(FILE:MaxFilePath + 1)
OutExtName cSTRING(FILE:MaxFilePath + 1)
!AnswerString STRING(FILE:MaxFilePath) !<-- poor
CharNDX uShort
ExtLen uShort
CurDir cSTRING(2)
end
!MyFilter &Cstring !<--- did I do this right?
code
! lcl.Extensions = 'Bitmaps<0>*.bmp<0>JPEG<0>*.jpg;*.jpeg<0>TIFF<0>*.tif;*.tiff<0>All Files<0>*.*<0,0>'
lcl.Extensions = CLIP(xExtensions)! & '<0>{2}' !Pointer to a buffer containing pairs of null-terminated filter strings. The last string in the buffer must be terminated by two NULL characters.
lcl.ExtLen = len(CLIP(xExtensions))
loop lcl.CharNDX = 1 to lcl.ExtLen
if lcl.Extensions[lcl.CharNDX] = '|'
lcl.Extensions[lcl.CharNDX] = '<0>'
end
! lcl.CharNDX = INSTRING('|',lcl.Extensions,1)
! if lcl.CharNDX
! lcl.Extensions[ lcl.CharNDX ] = '<0>'
! else
! break
! end
end
lcl.Extensions[lcl.ExtLen + 1] = '<0>'
lcl.Extensions[lcl.ExtLen + 2] = '<0>'
lcl.DefaExt = 'BMP' !<--- hard wired bug
lcl.FileName = CLIP(xInOutFileName) & '<0>'
lcl.CurDir = '.'
!MyFilter &= new cSTRING( len(CLIP(Extensions)) + 1) !<--- did I do this right?
!MyFilter = Extensions !<--- did I do this right?
!wouldn't it be easier to use const *cstring extensions
!todo !add logic to support NULL extensions -- I think above can GPF if null !!
lcl.MyOFN.lStructSize = size(OpenFileName) !DWORD
lcl.MyOFN.hwndOwner = 0{prop:Handle} !HWND
lcl.MyOFN.hInstance = 0 !HINSTANCE
lcl.MyOFN.lpstrFilter = address(lcl.Extensions) !LPCTSTR
lcl.MyOFN.lpstrCustomFilter = 0 !LPTSTR
lcl.MyOFN.nMaxCustFilter = 0 !DWORD
lcl.MyOFN.nFilterIndex = oGLO.INI_Non_Pos.Fetch('FileSave','ExtNum', 1) !DWORD
lcl.MyOFN.lpstrFile = address(lcl.FileName) !LPTSTR
lcl.MyOFN.nMaxFile = size(lcl.FileName) - 1 !DWORD
lcl.MyOFN.lpstrFileTitle = address(lcl.BaseName) !LPTSTR
lcl.MyOFN.nMaxFileTitle = size(lcl.BaseName) - 1 !DWORD
lcl.MyOFN.lpstrInitialDir = address(lcl.CurDir ) !0 !LPCTSTR
if omitted(argNum::Title)
lcl.MyOFN.lpstrTitle = 0
else
lcl.DialogTitle = xTitle
lcl.MyOFN.lpstrTitle = address(lcl.DialogTitle) !LPCTSTR
end
lcl.MyOFN.Flags = OFN_NOCHANGEDIR + OFN_OVERWRITEPROMPT + OFN_PATHMUSTEXIST + OFN_NOREADONLYRETURN + |
OFN_HIDEREADONLY
!OFN_EXPLORER + OFN_ENABLEHOOK + OFN_ENABLESIZING
lcl.MyOFN.nFileOffset = 0 !WORD
lcl.MyOFN.nFileExtension = 0 !WORD
lcl.MyOFN.lpstrDefExt = address(lcl.DefaExt) !LPCTSTR
lcl.MyOFN.lCustData = 0 !address(lcl.MyMGCustData) !DWORD
lcl.MyOFN.lpfnHook = 0 !address(MyOFNHookProc) !LPOFNHOOKPROC
lcl.MyOFN.lpTemplateName = 0 !LPCTSTR
! lcl.MyMGCustData.FilePath = 'origpath' !cSTRING(MAX_PATH)
! lcl.MyMGCustData.FileSelected = 'origFileSelected' !cSTRING(MAX_PATH)
!rintDebugSTRING('MySaveFileName pre UnlockThread Address(lcl.MyOFN) ['& address(lcl.MyOFN) &']<13,10>')
UnLockThread
lcl.RetVal = GetSaveFileName( lcl.MyOFN ) !*OpenFileNameType),bool,pascal,name('GetSaveFileName' & ANSI)
LockThread
!rintDebugSTRING('MySaveFileName post LockThread, lcl.RetVal ['& lcl.RetVal &']<13,10>')
if ~lcl.RetVal
lcl.ExtErr = CommDlgExtendedError()
if lcl.ExtErr <> CDERR_GENERALCODES
Message('Extended Error ['& CLIP(CommDlgExtendedError_Describe(lcl.ExtErr)) &']') ! lcl.MyOFN.lStructSize ['& lcl.MyOFN.lStructSize &']')
!else
! Message('cancel was pressed.')
end
else
xInOutFileName = lcl.FileName
oGLO.INI_Non_Pos.Update('FileSave','ExtNum', lcl.MyOFN.nFilterIndex)
!!! !Message('lcl.Retval ['& lcl.Retval &']')
!!!
!!! !memcpy( address(argFileName) , lcl.MyOFN.lpstrFile , lcl.MyOFN.nMaxFile ) !<-- prob. this is a CW String,
!!!
!!! !The following command is a bad idea: as it points to a CW String of unknown length
!!! !memcpy( address(argFileName) , lcl.MyOFN.lpstrFile , lcl.MyOFN.nMaxFile )
!!!
!!! !memcpy( address(lcl.OutFileName) , lcl.MyOFN.lpstrFile , lcl.MyOFN.nMaxFile )
!!! !memcpy( address(lcl.OutBaseName) , lcl.MyOFN.lpstrFileTitle, lcl.MyOFN.nMaxFileTitle)
!!! lcl.OutFileName = lcl.FileName
!!! lcl.OutPathName = lcl.FileName[ 1 : lcl.MyOfn.nFileOffset - 1 ]
!!! lcl.OutBaseName = lcl.FileName[ lcl.MyOfn.nFileOffset + 1 : lcl.MyOfn.nFileExtension - 1 ]
!!! lcl.OutExtName = lcl.FileName[ lcl.MyOfn.nFileExtension + 1 : len(CLIP(lcl.FileName)) ]
!!!
!!!
!!!
!!!
!!! !Start initial file name will have no extention
!!! !Store in INI, last save nFilterIndex, pass that in
!!!
!!!
!!!
!!! !Plan: Determine the returned extension
!!! ! Determine the save as extension (via nFilterIndex)
!!! !If the save as extension is all (*.*)
!!! !then
!!! ! done (assuming lcl.DefaExt is a valid extension)
!!! !Else
!!! ! if returned ext <> saved ext then strip and append
!!! ! see nFileExtension
!!! !end
!!!
!!! !if the returned path is same as the current path then return BaseName else return full FileName
!!!
!!! PrintDebugSTRING('-- 123456789-123456789-123456789-123456789-123456789-123456789-<13,10>')
!!! PrintDebugSTRING('-- lcl.OutFileName ['& CLIP(lcl.OutFileName) &']<13,10>') !<-- must still INCLUDE a <0>
!!! PrintDebugSTRING('-- lcl.OutPathName ['& CLIP(lcl.OutPathName) &']<13,10>') !<-- must still INCLUDE a <0>
!!! PrintDebugSTRING('-- lcl.OutBaseName ['& CLIP(lcl.OutBaseName) &']<13,10>') !<-- must still INCLUDE a <0>
!!! PrintDebugSTRING('-- lcl.OutExtName ['& CLIP(lcl.OutExtName ) &']<13,10>') !<-- must still INCLUDE a <0>
!!! PrintDebugSTRING('-- argFileName ['& CLIP(argFileName) &']<13,10>') !<-- must still INCLUDE a <0>
!!! PrintDebugSTRING('--<13,10>')
!!! PrintDebugSTRING('-- lcl.MyOFN.nFileOffset ['& lcl.MyOFN.nFileOffset &']<13,10>')
!!! PrintDebugSTRING('-- lcl.MyOFN.nFileExtension ['& lcl.MyOFN.nFileExtension &']<13,10>')
!!! PrintDebugSTRING('-- lcl.DefaExt ['& lcl.DefaExt &']<13,10>')
!!! !!!memcpy( address(lcl.OutDefaExt), lcl.MyOFN.lpstrDefExt, 3)
!!! PrintDebugSTRING('-- lcl.MyOFN.lpstrDefExt ['& lcl.MyOFN.lpstrDefExt &']<13,10>')
!!! PrintDebugSTRING('-- lcl.MyOFN.nFilterIndex ['& lcl.MyOFN.nFilterIndex &']<13,10>')
!!! PrintDebugSTRING('-- lcl.MyOFN.nMaxFile ['& lcl.MyOFN.nMaxFile &']<13,10>')
!!! PrintDebugSTRING('-- lcl.MyOFN.nMaxFileTitle ['& lcl.MyOFN.nMaxFileTitle &']<13,10>')
!!!
!!! !! if band(lcl.MyOFN.Flags, OFN_EXTENSIONDIFFERENT)
!!! !! !Testing (win2k) shows that this is ONLY false if the user enters the 3 letter extension pointed to by lpstrDefExt
!!! !! ! in which case the result will be those 3 letters
!!! !! ! NOTE: testing with a 7 char DefExt shows it will append the full 7 letters if 'ALL' is the save type
!!! !! ! however ExtensionDifferent will still show TRUE even if the user enters the 7 char DefExt, they must do the 3 char DefExt
!!! !!
!!! !! !Will occur if the user (correctly) leaves the extension off, and has it automagically appended!
!!! !! PrintDebugSTRING('--<13,10>')
!!! !! PrintDebugSTRING('User typed an Extension that is different from the Save As extension<13,10>')
!!! !! PrintDebugSTRING('--<13,10>')
!!! !!
!!! !! !todo:
!!! !! ! Warn the user?
!!! !! ! If the user entered a valid extension, then what?
!!! !!
!!! !! ! If changing extension
!!! !! ! strip of the extension
!!! !! ! find the save as extension
!!! !! ! append the save as extension
!!! !! ! end
!!! !!
!!! !! ! if lcl.MyOFN.nFileExtension
!!! !! ! Fname_NoExt = argFileName[ 1 : lcl.MyOFN.nFileExtension ]
!!! !! ! else !Last Char could be '.' or User entered no extension
!!! !! ! todo
!!! !! ! end
!!! !! end
end
return lcl.Retval
!=============================================================================================
!! MyOFNHookProc Procedure(HWND hDlg, | // handle to child dialog window
!! UINT uiMsg, | // message identifier
!! WPARAM wParam,| // message parameter
!! LPARAM lParam | // message parameter
!! )
!!
!! MyOFNotify &OFNotify
!! MyOpenFileName &OpenFileName
!! !MyCustData &MGCustData
!! Answer Bool
!! code
!! PrintDebugSTRING('MyOFNHookProc hDlg['& hDlg &'] uiMsg['& uiMsg &'] wParam['& wParam &'] lParam['& lParam &']<13,10>') !<-- is this safe?
!! case uiMsg
!! of WM_INITDIALOG ! LPARAM is a pointer to an OpenFileName structure
!! SetWindowLong(hDlg, DWL_USER, lParam) !Save the long pointer to the OPENFILENAME structure.
!! PrintDebugSTRING('MyOFNHookProc WM_INITDIALOG<13,10>')
!!
!! of WM_DESTROY
!! PrintDebugSTRING('MyOFNHookProc WM_DESTROY<13,10>')
!! ! MyOFNotify &= ( GetWindowLong(hdlg, DWL_USER) ) !Retrieve OpenFileName Pointer
!! ! MyOpenFileName &= ( MyOFNotify.lpOFN )
!! ! MyCustData &= ( MyOpenFileName.lCustData )
!! ! GetDlgItemText(hDlg, IDE_PATH , MyCustData.FilePath , size(MyCustData.FilePath) )
!! ! GetDlgItemText(hDlg, IDE_SELECTED, MyCustData.FileSelected , size(MyCustData.FileSelected) )
!!
!! of WM_NOTIFY ! LPARAM is a pointer to an OFNotify structure
!! PrintDebugSTRING('MyOFNHookProc WM_NOTIFY<13,10>')
!! !MyOFNGroup = lParam !<-- need to cast the pointer, Is this right?
!! MyOFNotify &= (lParam) !<-- need to cast the pointer, Is this right?
!! Answer = MyProcess_OFNotify(hDlg, MyOFNotify)
!! !Answer = MyProcess_OFNotify(hDlg, lParam)
!!
!! else
!! !PrintDebugSTRING('MyOFNHookProc 100<13,10>') !<-- is this safe?
!!
!! !case uiMsg
!! ! of mod:cdmsgShareViolation ! = RegisterWindowMessage(szmsgSHAREVIOLATION);
!! ! of mod:cdmsgFileOK ! = RegisterWindowMessage(szmsgFILEOK);
!! ! of mod:cdmsgHelp ! = RegisterWindowMessage(szCommdlgHelp);
!! !else return FALSE
!! !end
!! end
!! !PrintDebugSTRING('MyOFNHookProc 999<13,10>') !<-- is this safe?
!! return TRUE !0 !0 !let the default dialog box procedure process the message
!! !another example shows return TRUE !<-- will have to understand
!!
!! !---MSDN---
!! ! If the hook procedure returns zero, the default dialog box procedure processes the message.
!! !
!! ! If the hook procedure returns a nonzero value, the default dialog box procedure ignores the message.
!! !
!! ! For the CDN_SHAREVIOLATION and CDN_FILEOK notification messages,
!! ! the hook procedure should return a nonzero value to indicate
!! ! that it has used the SetWindowLong function to set a nonzero DWL_MSGRESULT value.
!! !---MSDN---
!!
!!
!!
!!
!! !=============================================================================================
!! MyProcess_OFNotify Procedure(HWND hDlg, *OFNotify ofn)
!!
!! !#define CDN_FIRST (0U-601U)
!! !#define CDN_LAST (0U-699U)
!! !
!! !// Notifications when Open or Save dialog status changes
!! !#define CDN_INITDONE (CDN_FIRST - 0x0000)
!! !#define CDN_SELCHANGE (CDN_FIRST - 0x0001)
!! !#define CDN_FOLDERCHANGE (CDN_FIRST - 0x0002)
!! !#define CDN_SHAREVIOLATION (CDN_FIRST - 0x0003)
!! !#define CDN_HELP (CDN_FIRST - 0x0004)
!! !#define CDN_FILEOK (CDN_FIRST - 0x0005)
!! !#define CDN_TYPECHANGE (CDN_FIRST - 0x0006)
!!
!!
!! CDN_FIRST EQUATE(-601) !(0U-601U) !<---- is this correct?
!! CDN_LAST EQUATE(-699) !(0U-699U)
!! Itemize,pre
!! CDN_TYPECHANGE EQUATE(CDN_FIRST - 6) !The user selected a new file type from the list of file types.
!! CDN_FILEOK EQUATE !The user clicked the OK button; the dialog box is about to close.
!! CDN_HELP EQUATE !The user clicked the Help button.
!! CDN_SHAREVIOLATION EQUATE !The common dialog box encountered a sharing violation on the file about to be returned.
!! CDN_FOLDERCHANGE EQUATE !The user opened a new folder or directory.
!! CDN_SELCHANGE EQUATE !The user selected a new file or folder from the file list.
!! CDN_INITDONE EQUATE ! - 0 !The system has finished initializing the dialog box, and the dialog box has finished processing the WM_INITDIALOG message. Also, the system has finished arranging controls in the common dialog box to make room for the controls of the child dialog box (if any).
!! end
!!
!! szFile cSTRING(MAX_PATH)
!!
!! code
!! PrintDebugSTRING('MyProcess_OFNotify ofn.hdr.TheCode ['& ofn.hdr.TheCode &']<13,10>')
!! ! PrintDebugSTRING('MyProcess_OFNotify ofn.hdr.TheCode ['& lclOFN.TheCode &']<13,10>')
!! ! case lclOFN.TheCode
!!
!! case ofn.hdr.TheCode !MG: modification, should be CODE vs. TheCode
!! of CDN_FILEOK ; !The user clicked the OK button; the dialog box is about to close.
!! of CDN_FOLDERCHANGE ; !The user opened a new folder or directory.
!! ! if CommDlg_OpenSave_GetFolderPath(GetParent(hDlg), szFile, sizeof(szFile)) <= sizeof(szFile))
!! ! ! // Display this new path in the appropriate box.
!! ! SetDlgItemText(hDlg, IDE_SELECTED, szFile)
!! ! end
!! of CDN_HELP ; !The user clicked the Help button.
!! of CDN_INITDONE ; !The system has finished initializing the dialog box, and the dialog box has finished processing the WM_INITDIALOG message. Also, the system has finished arranging controls in the common dialog box to make room for the controls of the child dialog box (if any).
!! of CDN_SELCHANGE ; !The user selected a new file or folder from the file list.
!! of CDN_SHAREVIOLATION ; !The common dialog box encountered a sharing violation on the file about to be returned.
!! of CDN_TYPECHANGE ; !The user selected a new file type from the list of file types.
!! end
!! !---MSDN---
!! ! If the hook procedure returns zero, the default dialog box procedure processes the message.
!! !
!! ! If the hook procedure returns a nonzero value, the default dialog box procedure ignores the message.
!! !
!! ! For the CDN_SHAREVIOLATION and CDN_FILEOK notification messages,
!! ! the hook procedure should return a nonzero value to indicate that
!! ! it has used the SetWindowLong function to set a nonzero DWL_MSGRESULT value.
!! !---MSDN---
!! return TRUE
!!
!=============================================================================================MyCommDlgExtendedError Procedure
CommDlgExtendedError_Describe Procedure(DWORD argExtErr)
lclText STRING(30)
!lclExtERR DWORD
code
!lclExtERR = CommDlgExtendedError()
case argExtErr
!---------- The following general error codes can be returned for any of the common dialog box functions
!123456789-123456789-123
of CDERR_DIALOGFAILURE ; lclText='CDERR_DIALOGFAILURE ' !EQUATE(0xFFFF)
of CDERR_GENERALCODES ; lclText='CDERR_GENERALCODES ' !EQUATE(0000h)
of CDERR_STRUCTSIZE ; lclText='CDERR_STRUCTSIZE ' !EQUATE(0001h)
of CDERR_INITIALIZATION ; lclText='CDERR_INITIALIZATION ' !EQUATE(0002h)
of CDERR_NOTEMPLATE ; lclText='CDERR_NOTEMPLATE ' !EQUATE(0003h)
of CDERR_NOHINSTANCE ; lclText='CDERR_NOHINSTANCE ' !EQUATE(0004h)
of CDERR_LOADSTRFAILURE ; lclText='CDERR_LOADSTRFAILURE ' !EQUATE(0005h)
of CDERR_FINDRESFAILURE ; lclText='CDERR_FINDRESFAILURE ' !EQUATE(0006h)
of CDERR_LOADRESFAILURE ; lclText='CDERR_LOADRESFAILURE ' !EQUATE(0007h)
of CDERR_LOCKRESFAILURE ; lclText='CDERR_LOCKRESFAILURE ' !EQUATE(0008h)
of CDERR_MEMALLOCFAILURE ; lclText='CDERR_MEMALLOCFAILURE ' !EQUATE(0009h)
of CDERR_MEMLOCKFAILURE ; lclText='CDERR_MEMLOCKFAILURE ' !EQUATE(000Ah)
of CDERR_NOHOOK ; lclText='CDERR_NOHOOK ' !EQUATE(000Bh)
of CDERR_REGISTERMSGFAIL ; lclText='CDERR_REGISTERMSGFAIL ' !EQUATE(000Ch)
!------------ The following error codes can be returned for the PrintDlg function:
of PDERR_PRINTERCODES ; lclText='PDERR_PRINTERCODES ' !EQUATE(1000h)
of PDERR_SETUPFAILURE ; lclText='PDERR_SETUPFAILURE ' !EQUATE(1001h)
of PDERR_PARSEFAILURE ; lclText='PDERR_PARSEFAILURE ' !EQUATE(1002h)
of PDERR_RETDEFFAILURE ; lclText='PDERR_RETDEFFAILURE ' !EQUATE(1003h)
of PDERR_LOADDRVFAILURE ; lclText='PDERR_LOADDRVFAILURE ' !EQUATE(1004h)
of PDERR_GETDEVMODEFAIL ; lclText='PDERR_GETDEVMODEFAIL ' !EQUATE(1005h)
of PDERR_INITFAILURE ; lclText='PDERR_INITFAILURE ' !EQUATE(1006h)
of PDERR_NODEVICES ; lclText='PDERR_NODEVICES ' !EQUATE(1007h)
of PDERR_NODEFAULTPRN ; lclText='PDERR_NODEFAULTPRN ' !EQUATE(1008h)
of PDERR_DNDMMISMATCH ; lclText='PDERR_DNDMMISMATCH ' !EQUATE(1009h)
of PDERR_CREATEICFAILURE ; lclText='PDERR_CREATEICFAILURE ' !EQUATE(100Ah)
of PDERR_PRINTERNOTFOUND ; lclText='PDERR_PRINTERNOTFOUND ' !EQUATE(100Bh)
of PDERR_DEFAULTDIFFERENT ; lclText='PDERR_DEFAULTDIFFERENT ' !EQUATE(100Ch)
!------------- The following error codes can be returned for the ChooseFont function:
of CFERR_CHOOSEFONTCODES ; lclText='CFERR_CHOOSEFONTCODES ' !EQUATE(2000h)
of CFERR_NOFONTS ; lclText='CFERR_NOFONTS ' !EQUATE(2001h)
of CFERR_MAXLESSTHANMIN ; lclText='CFERR_MAXLESSTHANMIN ' !EQUATE(2002h)
!------------- The following error codes can be returned for the GetOpenFileName and GetSaveFileName functions:
of FNERR_FILENAMECODES ; lclText='FNERR_FILENAMECODES ' !equate(3000h) !MG: not in my MSDN
of FNERR_SUBCLASSFAILURE ; lclText='FNERR_SUBCLASSFAILURE ' !equate(3001h)
of FNERR_INVALIDFILENAME ; lclText='FNERR_INVALIDFILENAME ' !equate(3002h)
of FNERR_BUFFERTOOSMALL ; lclText='FNERR_BUFFERTOOSMALL ' !equate(3003h)
!------------- The following error code can be returned for the FindText and ReplaceText functions:
of FRERR_FINDREPLACECODES ; lclText='FRERR_FINDREPLACECODES ' !equate(4000h)
of FRERR_BUFFERLENGTHZERO ; lclText='FRERR_BUFFERLENGTHZERO ' !equate(4001h) !FindText and ReplaceText
!------------- MG: assumed to be for ChoseColor
of CCERR_CHOOSECOLORCODES ; lclText='CCERR_CHOOSECOLORCODES ' !equate(5000h) !MG: Not in my MSDN
else lclText='Uknown Code ['& argExtERR &']'
end !case
lclText = '[' & argExtErr &'] ' & CLIP(lclText)
return lclText
!Windows Naming Conventions - used in Clarion prototypes
!
OMIT('WeReallyNeedAnIFDEF',MAX_PATH > 0)
MAX_PATH EQUATE(260)
!END-OMIT('WeReallyNeedAnIFDEF',MAX_PATH)
OMIT('_SVAPI_WasIncluded_',_WINAPI_)
HANDLE EQUATE(UNSIGNED)
HWND EQUATE(HANDLE)
HINSTANCE EQUATE(HANDLE)
HMODULE EQUATE(HINSTANCE)
HBITMAP EQUATE(HANDLE)
HBRUSH EQUATE(HANDLE)
HFONT EQUATE(HANDLE)
HRGN EQUATE(HANDLE)
HGLOBAL EQUATE(HANDLE)
HPEN EQUATE(HANDLE)
UINT EQUATE(UNSIGNED)
DWORD EQUATE(ULONG)
ATOM EQUATE(UINT)
COLORREF EQUATE(DWORD)
!end-OMIT('_SVAPI_WasIncluded_',_WINAPI_)
omit('*** ifdef_WinEqu ***',ifDef_WinEqu)
ifDef_WinEqu EQUATE(1)
FOURCC EQUATE(LONG)
WCHAR EQUATE(BYTE)
UCHAR EQUATE(BYTE)
CHAR EQUATE(BYTE)
BOOL EQUATE(SIGNED)
BYTE EQUATE(BYTE)
WORD EQUATE(SIGNED)
DWORD EQUATE(ULONG)
LPVOID EQUATE(ULONG)
PVOID EQUATE(ULONG)
FLOAT EQUATE(SREAL)
LPSTR EQUATE(CSTRING) !Usage:Pass the Label of the LPSTR !<-- bad
LPCSTR EQUATE(CSTRING) !Usage:Pass the Label of the LPCSTR !<-- bad
HTASK EQUATE(HANDLE)
HDC EQUATE(HANDLE)
WPARAM EQUATE(UINT)
LPARAM EQUATE(LONG)
LRESULT EQUATE(LONG)
LPBOOL EQUATE(ULONG)
LPCVOID EQUATE(ULONG)
HDIOBJ EQUATE(HANDLE)
HCOLORSPACE EQUATE(HANDLE)
HRDVR EQUATE(HANDLE)
HWAVEOUT EQUATE(HANDLE)
HWAVEIN EQUATE(HANDLE)
HACCEL EQUATE(HANDLE)
HWINSTA EQUATE(HANDLE)
HKL EQUATE(HANDLE)
HPALETTE EQUATE(HANDLE)
HHOOK EQUATE(HANDLE)
HDRVR EQUATE(HANDLE)
HDWP EQUATE(HANDLE)
HRSRC EQUATE(HANDLE)
HSTR EQUATE(HANDLE)
HCURSOR EQUATE(HANDLE)
HICON EQUATE(HCURSOR)
HGRN EQUATE(HANDLE)
HMENU EQUATE(HANDLE)
SC_HANDLE EQUATE(HANDLE)
HDESK EQUATE(HANDLE)
HENHMETAFILE EQUATE(HANDLE)
HSZ EQUATE(WORD)
HMETAFILE EQUATE(HANDLE)
HMIDIIN EQUATE(HANDLE)
HMIDIOUT EQUATE(HANDLE)
HMMIO EQUATE(HANDLE)
HFILE EQUATE(SIGNED)
LUID EQUATE(LONG)
PLUID EQUATE(LONG)
ANYSIZE_ARRAY EQUATE(1)
PHANDLE EQUATE(HANDLE)
SPHANDLE EQUATE(HANDLE)
LPHANDLE EQUATE(HANDLE)
HLOCAL EQUATE(HANDLE)
GLOBALHANDLE EQUATE(HANDLE)
LOCALHANDLE EQUATE(HANDLE)
HDDEDATA EQUATE(DWORD)
HCONV EQUATE(DWORD)
HCONVLIST EQUATE(DWORD)
LONGREAL EQUATE(REAL)
DWORDLONG EQUATE(REAL)
WORDLONG EQUATE(REAL)
LARGE_INTEGER EQUATE(LONG)
ULARGE_INTEGER EQUATE(ULONG)
BOOLEAN EQUATE(BYTE)
VERSION EQUATE(UNSIGNED)
!end-omit('*** ifdef_WinEqu ***',ifDef_WinEqu)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment