标题:我也来谈谈我对结构的理解
取消只看楼主
sam_jiang
Rank: 8Rank: 8
等 级:贵宾
威 望:10
帖 子:542
专家分:781
注 册:2021-10-13
结帖率:97.44%
已结贴  问题点数:20 回复次数:8 
我也来谈谈我对结构的理解
个人觉得结构就是一个格式化的字符串,它和类有些类似,可以继承,但没有封装方法。

如果把结构看做类,那么结构的成员就相当于类的属性。

下面是point结构的一个定义
Type POINTAPI
    x As Long
    y As Long
End Type

通过point.x来访问结构的成员x,这跟我们的类不是很像吗?

我们来构建一个point类吧。
第一步,构建一个通用类struct
**************************************************
*-- Class:        struct (d:\documents\visual foxpro 项目\myclass.vcx)
*-- ParentClass:  custom
*-- BaseClass:    custom
*-- Time Stamp:   11/03/22 11:51:11 AM
*****************设置一个通用类*******************
DEFINE CLASS struct AS custom

    *-- 用以储存或设置结构体数据
    struct = ""
    Name = "struct"


    *-- 设置结构体
    PROCEDURE set
    ENDPROC

ENDDEFINE
*
*-- EndDefine: struct
**************************************************

第二步,构建point类

*****************************************************
*-- Class:        _point (d:\documents\visual foxpro 项目\myclass.vcx)
*-- ParentClass:  struct (d:\documents\visual foxpro 项目\myclass.vcx)
*-- BaseClass:    custom
*-- Time Stamp:   11/03/22 08:59:09 PM
********point类和系统同名,所以加了条下划线**********
DEFINE CLASS _point AS struct


    *-- x坐标
    x = .F.

    *-- Y坐标
    y = .F.


*!*    PROCEDURE struct_assign
*!*        LPARAMETERS vNewVal
*!*        *To do: Modify this routine for the Assign method
*!*        THIS.struct = m.vNewVal
*!*        this.x=CTOBIN(SUBSTR(m.vnewval,1,4),"4rs")
*!*        this.y=CTOBIN(SUBSTR(m.vnewval,5,4),"4rs")
*!*    ENDPROC


    PROCEDURE Init
        this.struct=REPLICATE(CHR(0),8) &&初始化结构体
    ENDPROC


    PROCEDURE set
            PARAMETERS xorcstruct,y

            DO case
                CASE PARAMETERS()=1 AND VARTYPE(xorcstruct)=="C" && 注意这里的xorcstruct不是数字,而是8字节字符,我并没有对字符串的有效性进行检查。
                this.x=CTOBIN(SUBSTR(xorcstruct,1,4),"4rs")
                this.y=CTOBIN(SUBSTR(xorcstruct,5,4),"4rs")
                this.struct=xorcstruct
            CASE PARAMETERS()=2
                this.x=xorcstruct
                this.y=y
                this.struct=BINTOC(xorcstruct,"4rs")+BINTOC(y,"4rs")
            ENDCASE
        *!*PARAMETERS x,y
        *!*this.struct=BINTOC(x,"4rs")+BINTOC(y,"4rs")

    ENDPROC


ENDDEFINE
*
*-- EndDefine: _point
**************************************************

第三步,实例化
*!* pointstructtest.prg
CLEAR
DECLARE integer GetCursorPos IN WIN32API string@
SET CLASSLIB TO "D:\Documents\Visual FoxPro 项目\myclass.VCX"
opoint=CREATEOBJECT("_point")
cstruct=opoint.struct
getcursorpos(@cstruct)
opoint.struct=cstruct
opoint.set(cstruct)
?opoint.x
?opoint.y
release opoint
clear dlls

************end**************

不知道这样的理解对大家有没有帮助???

[此贴子已经被作者于2022-11-6 16:01编辑过]

搜索更多相关主题的帖子: this struct visual 结构 point 
2022-11-06 15:56
sam_jiang
Rank: 8Rank: 8
等 级:贵宾
威 望:10
帖 子:542
专家分:781
注 册:2021-10-13
得分:0 
再来一个rectangle结构

类定义如下:
**************************************************
*-- Class:        rectangle (d:\documents\visual foxpro 项目\myclass.vcx)
*-- ParentClass:  struct (d:\documents\visual foxpro 项目\myclass.vcx)
*-- BaseClass:    custom
*-- Time Stamp:   11/07/22 04:18:08 PM
*
DEFINE CLASS rectangle AS struct

    *-- 左上角x坐标
    x = .F.

    *-- 左上角y坐标
    y = .F.

    PROCEDURE set
        PARAMETERS xorcstruct,y,nwidth,nheight

        DO case
            CASE PARAMETERS()=1 AND VARTYPE(xorcstruct)=="C" && 注意这里的xorcstruct不是数字,而是16字节字符,我并没有对字符串的有效性进行检查。
            this.x=CTOBIN(SUBSTR(xorcstruct,1,4),"4rs")
            this.y=CTOBIN(SUBSTR(xorcstruct,5,4),"4rs")
            this.width=CTOBIN(SUBSTR(xorcstruct,9,4),"4rs")
            this.height=CTOBIN(SUBSTR(xorcstruct,13,4),"4rs")
            this.struct=xorcstruct
        CASE PARAMETERS()=4
            this.x=xorcstruct
            this.y=y
            this.Width=nwidth
            this.Height=nheight
            this.struct=BINTOC(xorcstruct,"4rs")+BINTOC(y,"4rs")+BINTOC(nwidth,"4rs")+BINTOC(nheight,"4rs")
        OTHERWISE
            RETURN .f.
        ENDCASE
    ENDPROC

ENDDEFINE
*
*-- EndDefine: rectangle
**************************************************

获得_screen的rect

*getscreenrect.prg
CLEAR
DECLARE inte GetWindowRect IN WIN32API inte,string@
cstr=REPLICATE(CHR(0),16)
getwindowrect(_screen.HWnd,@cstr)
SET CLASSLIB TO myclass
orect=CREATEOBJECT("rectangle")
orect.set(cstr)
?"获得orect的端点值"
?orect.x
?orect.y
?orect.width
?orect.height
?"获得_screen的端点值,看是否相同"
?_screen.Left
?_screen.Top
?_screen.Width
?_screen.Height
RELEASE orect
CLEAR DLLS
SET CLASSLIB TO
2022-11-07 16:30
sam_jiang
Rank: 8Rank: 8
等 级:贵宾
威 望:10
帖 子:542
专家分:781
注 册:2021-10-13
得分:0 
回复 4楼 吹水佬
你这个比喻比较形象,一条记录就相当于一个结构体。
2022-11-07 20:50
sam_jiang
Rank: 8Rank: 8
等 级:贵宾
威 望:10
帖 子:542
专家分:781
注 册:2021-10-13
得分:0 
回复 6楼 厨师王德榜
抛砖引玉,在各位大佬面前班门弄斧了。。。
2022-11-07 20:56
sam_jiang
Rank: 8Rank: 8
等 级:贵宾
威 望:10
帖 子:542
专家分:781
注 册:2021-10-13
得分:0 
我们把结构封装为类,目的是省却foxer去记复杂的api函数声明,以及涩晦难懂的结构申明,所以还应该对我的point类进行改造。

改造后的point类如下:

**************************************************
*-- Class:        _point (d:\documents\visual foxpro 项目\myclass.vcx)
*-- ParentClass:  struct (d:\documents\visual foxpro 项目\myclass.vcx)
*-- BaseClass:    custom
*-- Time Stamp:   11/08/22 09:02:13 AM
*
DEFINE CLASS _point AS struct


    *-- x坐标
    x = .F.

    *-- Y坐标
    y = .F.


    PROCEDURE struct_assign
        LPARAMETERS vNewVal
        *To do: Modify this routine for the Assign method
        *!*    THIS.struct = m.vNewVal
        *!*    this.x=CTOBIN(SUBSTR(m.vnewval,1,4),"4rs")
        *!*    this.y=CTOBIN(SUBSTR(m.vnewval,5,4),"4rs")
    ENDPROC


    PROCEDURE set
        PARAMETERS xorcstruct,y

        DO case
            CASE PARAMETERS()=1 AND VARTYPE(xorcstruct)=="C" && 注意这里的xorcstruct不是数字,而是8字节字符,我并没有对字符串的有效性进行检查。
            this.x=CTOBIN(SUBSTR(xorcstruct,1,4),"4rs")
            this.y=CTOBIN(SUBSTR(xorcstruct,5,4),"4rs")
            this.struct=xorcstruct
        CASE PARAMETERS()=2
            this.x=xorcstruct
            this.y=y
            this.struct=BINTOC(xorcstruct)+BINTOC(y)
        OTHERWISE
            RETURN .f.
        ENDCASE
        *!*    PARAMETERS x,y
        *!*    this.struct=BINTOC(x,"4rs")+BINTOC(y,"4rs")

    ENDPROC


    PROCEDURE Init
        DECLARE integer GetCursorPos IN WIN32API string@
    ENDPROC


    PROCEDURE Destroy
        CLEAR DLLS
    ENDPROC


    *-- 获取当前鼠标所在点的位置,成功返回.t.
    PROCEDURE get
        cstruct=opoint.struct
        getcursorpos(@cstruct)
        this.set(cstruct)
    ENDPROC


ENDDEFINE
*
*-- EndDefine: _point
**************************************************


这样用户就不需要申明api函数了,直接用就可以了。

***pointtest.prg***
CLEAR
SET CLASSLIB TO "D:\Documents\Visual FoxPro 项目\myclass.VCX"
opoint=CREATEOBJECT("_point")
opoint.get()
?opoint.x
?opoint.y
release opoint
**************

当需要将一个确定的点以结构体的形式当参数传给其他函数yourfunc,可以这样用:

opoint.set(200,500) &&设置坐标点(200,500)
yourfunc(opoint.struct) &&传给你的函数






[此贴子已经被作者于2022-11-8 09:18编辑过]

2022-11-08 09:15
sam_jiang
Rank: 8Rank: 8
等 级:贵宾
威 望:10
帖 子:542
专家分:781
注 册:2021-10-13
得分:0 
改造后的rectangle类如下:

**************************************************
*-- Class:        rectangle (d:\documents\visual foxpro 项目\myclass.vcx)
*-- ParentClass:  struct (d:\documents\visual foxpro 项目\myclass.vcx)
*-- BaseClass:    custom
*-- Time Stamp:   11/08/22 09:41:07 AM
*
DEFINE CLASS rectangle AS struct

    *-- 左上角x坐标
    x = .F.

    *-- 左上角y坐标
    y = .F.

    *-- 获得form或window窗体位置的矩形结构,成功返回.t.
    PROCEDURE get
        PARAMETERS Oform

        IF !VARTYPE(oform)=="O"
            RETURN .f.
        ENDIF

        IF oform.class=="Form" OR oform=_vfp
            cstruct=this.struct
            getwindowrect(oform.hwnd,@cstruct)
            this.set(cstruct)
            RETURN .t.
        ELSE
            RETURN .f.
        ENDIF

    ENDPROC


    PROCEDURE Destroy
        CLEAR DLLS
    ENDPROC

    PROCEDURE Init
        DECLARE integer GetWindowRect IN WIN32API integer nhwnd, string @rect
    ENDPROC

    PROCEDURE set
        PARAMETERS xorcstruct,y,nwidth,nheight

        DO case
            CASE PARAMETERS()=1 AND VARTYPE(xorcstruct)=="C" && 注意这里的xorcstruct不是数字,而是16字节字符,我并没有对字符串的有效性进行检查。
            this.x=CTOBIN(SUBSTR(xorcstruct,1,4),"4rs")
            this.y=CTOBIN(SUBSTR(xorcstruct,5,4),"4rs")
            this.width=CTOBIN(SUBSTR(xorcstruct,9,4),"4rs")
            this.height=CTOBIN(SUBSTR(xorcstruct,13,4),"4rs")
            this.struct=xorcstruct
        CASE PARAMETERS()=4
            this.x=xorcstruct
            this.y=y
            this.Width=nwidth
            this.Height=nheight
            this.struct=BINTOC(xorcstruct,"4rs")+BINTOC(y,"4rs")+BINTOC(nwidth,"4rs")+BINTOC(nheight,"4rs")
        OTHERWISE
            RETURN .f.
        ENDCASE
    ENDPROC

ENDDEFINE
*
*-- EndDefine: rectangle
**************************************************

实例:
***getscreenrect()
CLEAR
SET CLASSLIB TO myclass
orect=CREATEOBJECT("rectangle")
orect.get(_screen) &&只支持自定义form,_screen和_vfp
?"获得orect的端点值"
?orect.x
?orect.y
?orect.width
?orect.height
?"获得_screen的端点值,看是否相同"
?_screen.Left
?_screen.Top
?_screen.Width
?_screen.Height
RELEASE orect
SET CLASSLIB TO  
******end******

2022-11-08 09:50
sam_jiang
Rank: 8Rank: 8
等 级:贵宾
威 望:10
帖 子:542
专家分:781
注 册:2021-10-13
得分:0 
回复 14楼 吹水佬
是的,我欠缺考虑,rectangle类的destroy事件应该改为 clear dlls "GetWindowRect",_point类的destroy事件应该改为 clear dlls "GetCursorPos" 。这样就不会误杀了。
2022-11-08 20:09
sam_jiang
Rank: 8Rank: 8
等 级:贵宾
威 望:10
帖 子:542
专家分:781
注 册:2021-10-13
得分:0 
虽说是小概率事件,但确实有那个可能,依旧误杀。不过这个问题可以解决,申明API函数前先查一下是否此函数已经申明,已申明则说明有其他程序也在使用,就不要释放。

鉴于每个结构都是独一无二的,没办法,只能为每一个结构创建一个类,创建通用类怕是不行的。

大多数狐友都不是很了解结构,而实际上却有使用结构的需求。他们不可能像你们那样了解它,那么写这样的结构类就可以帮到他们!

事实上,系统里的GDIPLUS类,以及狐友提供的System.drawing类,就是把结构以及API函数封装起来,供使用者调用,而不必关心怎么申明API函数,以及如何使用结构。
2022-11-10 02:00
sam_jiang
Rank: 8Rank: 8
等 级:贵宾
威 望:10
帖 子:542
专家分:781
注 册:2021-10-13
得分:0 
根据csyx的意见,我再改造一下point类!

init事件:
*******************************************************************************
ndeclared=ADLLS(cdlls)
IF ndeclared>0
    IF ASCAN(cdlls,"GetCursorPos")>0
        this.declared=.t.
    ENDIF        
    RELEASE cdlls
ELSE     
    DECLARE integer GetCursorPos IN WIN32API string@
    this.declared=.f.
ENDIF

RELEASE ndeclared

*******************************************************************************

destory事件:

IF this.declared=.f.
    CLEAR DLLS "GetCursorPos"
ENDIF

rectangle类的改造如下:

init事件:
*******************************************************************************        
ndeclared=ADLLS(cdlls)
IF ndeclared>0
    IF ASCAN(cdlls,"GetWindowRect")>0
        this.declared=.t.
   
    ENDIF        
    RELEASE cdlls
ELSE     
    DECLARE integer GetWindowRect IN WIN32API integer, string@
    this.declared=.f.
ENDIF
RELEASE ndeclared   

destroy事件:
*******************************************************************************   
IF this.declared=.f.
    CLEAR DLLS "GetWindowRect"
ENDIF

*********************************The End***************************************     
2022-11-11 13:20



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-510569-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.017693 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved