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