| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1411 人关注过本帖
标题:我也来谈谈我对结构的理解
只看楼主 加入收藏
iswith
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:5
帖 子:443
专家分:582
注 册:2013-5-14
收藏
得分:0 
以下是引用吹水佬在2022-11-7 16:19:12的发言:

可以说语句表达形式类似(写法有点像),实质就不是一回事。
结构是不同类型成员紧密有序集合的数据块(同一空间)。
结构还有特别的地方,就拿DBF说,每条记录就是一个结构块,声明一个相同结构的东东,套在记录的上就可以直接按结构成员读写每条记录字段的数据。就好象拿个饼印模在面团上面压盖,就可以压出一个一个一样的饼。这饼印就是结构,饼就是每条记录。

描述比较准确。。。。有序同一空间
2022-11-07 22:51
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:786
专家分:1160
注 册: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: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:786
专家分:1160
注 册: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
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:451
帖 子:10607
专家分:43182
注 册:2014-5-20
收藏
得分:0 
觉得这样来封装类有点浪费,没有充分发挥到类的作用。
类最大的特点是“继承”,子承父业。
这样封装只是一个类的“特例”,个人觉得还不如封装成调用API的函数来得简单清晰明了。
另:释构时的 CLEAR DLLS 杀伤力有点大,如果其他过程也有调用API就有可能出现“找不到xxxxx.prg”。
2022-11-08 10:09
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:786
专家分:1160
注 册:2021-10-13
收藏
得分:0 
回复 14楼 吹水佬
是的,我欠缺考虑,rectangle类的destroy事件应该改为 clear dlls "GetWindowRect",_point类的destroy事件应该改为 clear dlls "GetCursorPos" 。这样就不会误杀了。
2022-11-08 20:09
csyx
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:火星
等 级:版主
威 望:37
帖 子:703
专家分:2780
注 册:2018-3-13
收藏
得分:0 
以下是引用sam_jiang在2022-11-8 20:09:21的发言:

rectangle类的destroy事件应该改为 clear dlls "GetWindowRect",_point类的destroy事件应该改为 clear dlls "GetCursorPos" 。这样就不会误杀了。

一样是误杀,你不能假设人家就不声明和使用这两个api函数
另一方面,这样构造的结构类完全没必要,常用的win32api结构少说也有几百种,难不成使用一个就构造一个?设计一个通用的就得,只提供几个必要的方法即可 Define(用来定义结构成员),Parse(用于分解字符串块到各成员 or 类属性),toString(拼合各属性到一字符串)
如果使用者连结构的成员都不了解,也就没资格使用结构类了,直接封装win32api函数给他调用更简单


[此贴子已经被作者于2022-11-9 04:44编辑过]


这家伙很懒,啥也没留下
2022-11-09 04:39
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:786
专家分:1160
注 册:2021-10-13
收藏
得分:0 
虽说是小概率事件,但确实有那个可能,依旧误杀。不过这个问题可以解决,申明API函数前先查一下是否此函数已经申明,已申明则说明有其他程序也在使用,就不要释放。

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

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

事实上,系统里的GDIPLUS类,以及狐友提供的System.drawing类,就是把结构以及API函数封装起来,供使用者调用,而不必关心怎么申明API函数,以及如何使用结构。
2022-11-10 02:00
asdf_123000
Rank: 4
等 级:业余侠客
威 望:1
帖 子:273
专家分:227
注 册:2012-12-20
收藏
得分:0 
学习
2022-11-11 13:18
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:786
专家分:1160
注 册: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
schtg
Rank: 12Rank: 12Rank: 12
来 自:Usa
等 级:贵宾
威 望:67
帖 子:1712
专家分:3318
注 册:2012-2-29
收藏
得分:0 
回复 19楼 sam_jiang
谢谢!
2022-11-12 06:01
快速回复:我也来谈谈我对结构的理解
数据加载中...
 
   



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

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