VFP封装结构类型示例
近日,有贴谈到“调用Windows API时,如何正确地传递struct(结构体)参数”的问题。连接:https://bbs.bccn.net/thread-508544-1-1.html
VFP调用API涉及到结构类型,通常是用字符串来表达结构类型成员数据,这方法看似简单,
但易读性差,很不好理解,尤其对初接触调用API的容易搞错。
封装结构类型的类,可提高VFP语言的表达能力,提高学习编程效率。
示例以 PARAFORMAT2 结构简单描述,对于复杂的结构体有待探讨
程序代码:** VFP封装结构类型示例
** 思路:
** 定义一个二维数组(aSTRUCT)用来描述结构体成员属性
** 每一行表达一个成员属性:名称(Name),类型(Type), 大小(Size),地址偏移量(Offset)
** 定义 STRUCT_ARRAY 类,提供初始化结构成员属性函数 stInit()
** 定义 STRUCT_CALSS 类,提供读写结构成员数据函数 getValue()、setValue()
DECLARE long malloc IN msvcrt as apiMalloc long
DECLARE long free IN msvcrt as apiFree long
DECLARE long SendMessage IN user32 as apiSendMessage long,long,long,long
of = CREATEOBJECT("form1")
of.show(1)
CLEAR ALL
RETURN
DEFINE CLASS form1 as Form
ADD OBJECT rich AS Olecontrol WITH top=10,left=10,width=200,height=200,OleClass="RICHTEXT.RichtextCtrl.1",visible=1
PROCEDURE rich.init
this.text = ""
pf = CREATEOBJECT("PARAFORMAT2")
st = CREATEOBJECT("STRUCT_CALSS", pf)
st.setValue("cbSize", st.nSize)
st.setValue("dwMask", 256)
st.setValue("dyLineSpacing", 300)
st.setValue("bLineSpacingRule", 4)
#define WM_USER 0x0400
#define EM_SETPARAFORMAT (WM_USER + 71)
apiSendMessage(this.hWnd, EM_SETPARAFORMAT, 0, st.pBuffer)
RELEASE st,pf
this.text = "123456789"+0h0D0A+"abcdefghijk"+0h0D0A+"ABCDEFGHIJK"++0h0D0A
ENDPROC
ENDDEFINE
DEFINE CLASS PARAFORMAT2 AS STRUCT_ARRAY
PROCEDURE init
DIMENSION this.aSTRUCT[24,4]
this.stInit(1, "cbSize", "N",4) && DWORD
this.stInit(2, "dwMask", "N",4)
this.stInit(3, "wNumbering", "N",2) && WORD
this.stInit(4, "wEffects", "N",2)
this.stInit(5, "dxStartIndent", "N",4)
this.stInit(6, "dxRightIndent", "N",4)
this.stInit(7, "dxOffset", "N",4)
this.stInit(8, "wAlignment", "N",2)
this.stInit(9, "cTabCount", "N",2)
this.stInit(10, "rgxTabs", "C",128) && DWORD[MAX_TAB_STOPS], MAX_TAB_STOPS=32
this.stInit(11, "dySpaceBefore", "N",4)
this.stInit(12, "dySpaceAfter", "N",4)
this.stInit(13, "dyLineSpacing", "N",4)
this.stInit(14, "sStyle", "N",2)
this.stInit(15, "bLineSpacingRule", "N",1) && BYTE
this.stInit(16, "bOutlineLevel", "N",1)
this.stInit(17, "wShadingWeight", "N",2)
this.stInit(18, "wShadingStyle", "N",2)
this.stInit(19, "wNumberingStart", "N",2)
this.stInit(20, "wNumberingStyle", "N",2)
this.stInit(21, "wNumberingTab", "N",2)
this.stInit(22, "wBorderSpace", "N",2)
this.stInit(23, "wBorderWidth", "N",2)
this.stInit(24, "wBorders", "N",2)
ENDPROC
ENDDEFINE
DEFINE CLASS STRUCT_ARRAY AS Session
DIMENSION aSTRUCT[1,4]
PROCEDURE stInit(n, cName, cType, nSize)
this.aSTRUCT[n,1] = cName
this.aSTRUCT[n,2] = cType
this.aSTRUCT[n,3] = nSize
this.aSTRUCT[n,4] = IIF(n>1, this.aSTRUCT[n-1,3]+this.aSTRUCT[n-1,4], 0)
ENDFUNC
ENDDEFINE
DEFINE CLASS STRUCT_CALSS AS Session
stObj = NULL
pBuffer = 0
nSize = 0
PROCEDURE init(stObj)
this.stObj = stObj
LOCAL nRowCount
nRowCount = ALEN(this.stObj.aSTRUCT, 1)
this.nSize = this.stObj.aSTRUCT[nRowCount,3] + this.stObj.aSTRUCT[nRowCount,4]
this.pBuffer = apiMalloc(this.nSize)
SYS(2600, this.pBuffer, this.nSize, REPLICATE(0h00,this.nSize))
ENDPROC
PROCEDURE Destroy
apiFree(this.pBuffer)
ENDPROC
HIDDEN FUNCTION getRow(cName)
LOCAL nRow
nRow = ASCAN(this.stObj.aSTRUCT, cName)
RETURN IIF(nRow>0, ASUBSCRIPT(this.stObj.aSTRUCT,nRow,1), 0)
ENDFUNC
FUNCTION getValue(cName)
LOCAL n, nSize, nOffset, ret
n = this.getRow(cName)
IF n == 0
RETURN NULL
ENDIF
nSize = this.stObj.aSTRUCT[n,3]
nOffset = this.stObj.aSTRUCT[n,4]
RETURN ICASE(this.stObj.aSTRUCT[n,2]=="N", CTOBIN(SYS(2600, this.pBuffer+nOffset, nSize), TRANSFORM(nSize)+"RS"),;
this.stObj.aSTRUCT[n,2]=="C", SYS(2600, this.pBuffer+nOffset, nSize),;
NULL)
ENDFUNC
FUNCTION setValue(cName, vValue)
LOCAL n, nSize, nOffset, ret
n = this.getRow(cName)
IF n == 0
RETURN ""
ENDIF
nSize = this.stObj.aSTRUCT[n,3]
nOffset = this.stObj.aSTRUCT[n,4]
IF this.stObj.aSTRUCT[n,2]=="N" AND VARTYPE(vValue)=="N"
RETURN SYS(2600, this.pBuffer+nOffset, nSize, BINTOC(vValue, TRANSFORM(nSize)+"RS"))
ELSE
IF this.stObj.aSTRUCT[n,2]=="C" AND VARTYPE(vValue)=="C"
vValue = LEFT(vValue, nSize)
nSize = LEN(vValue)
RETURN SYS(2600, this.pBuffer+nOffset, nSize, vValue)
ENDIF
ENDIF
RETURN ""
ENDFUNC
ENDDEFINE









