围观一下高手如何在VFP中处理C语言的结构体(struct)
* ----------------------------* 这是从VFPX中复制的一段代码,功能是:调用comdlg32中的“保存文件”系统对话框。
* 当中自定义的PChar类,很有意思,通过它来轻松操作struct中需要用到的字段。
* ----------------------------
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)
RETURN BINTOC(lnValue, "4RS")
#if .f.
*---------------
* 注:老外原函数太过冗长,顺手改为上边的一句话搞定。
#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)
*---------------
#endif .f.
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