| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1799 人关注过本帖
标题:容器控件拦截容器内控件的方法
取消只看楼主 加入收藏
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:858
专家分:1334
注 册:2021-10-13
结帖率:97.22%
收藏
已结贴  问题点数:20 回复次数:11 
容器控件拦截容器内控件的方法
记得上次发帖求助grid控件的gridhittest事件无法获得正确结果,后来有兄弟用bindevent的方法解决了。但我总记得有简单的方法来传递控件事件给容器控件的,以前在网上有看到过,当时一直没想起来。

最近终于想起来了,分享给大家。今天百度了一下,这个方法叫冒泡事件。。。

想必大家都有用过container,pageframe,commandgroup,grid等容器控件,当点击容器内控件时,首先接收消息的是容器内的最内层的控件,而容器是接收不到的。就像上次我的gridhittest,在grid上点击事件被传递给cell,或者header了,导致gridhittest无法正常工作。而我们编程的过程中,肯定有希望让容器控件来接收用户的鼠标或键盘事件,而不是容器里的控件。举个例子,一个form上有很多控件,用户需要用鼠标动态调整控件的大小,而这些控件是联动的,这就很麻烦,因为要涉及到mousemove事件,当鼠标移动到控件上时,触发的是控件的mousemove事件,移走就触发form的mousemove事件了。。。

最近在写一个prg的文件管理程序,终于实现了!废话不多说,上代码吧。。。

程序代码:
PUBLIC oform1

oform1=NEWOBJECT("form1")
oform1.Show
RETURN


    **************************************************
*-- Form:         form1 (d:\documents\visual foxpro 项目\bubbledevent.scx)
*-- ParentClass:  form
*-- BaseClass:    form
*-- Time Stamp:   11/16/22 09:52:11 PM
*
DEFINE CLASS form1 AS form


    Height = 750
    Width = 1057
    DoCreate = .T.
    AutoCenter = .T.
    Caption = "Form1"
    WindowState = 0
    Name = "Form1"


    ADD OBJECT olecontrol1 AS olecontrol WITH ;
        Top = 35, ;
        Left = 1, ;
        Height = 24, ;
        Width = 280, ;
        Anchor = 0, ;&&当form调整大小时,控件也随之调整
        Name = "Olecontrol1"


    ADD OBJECT olecontrol3 AS olecontrol WITH ;
        Top = 61, ;
        Left = 1, ;
        Height = 688, ;
        Width = 280, ;
        Anchor = (64+2+1), ;&&当form调整大小时,控件也随之调整
        Name = "Olecontrol3"


    ADD OBJECT edit1 AS editbox WITH ;
        Anchor = (64+8+2+1), ; &&当form调整大小时,控件也随之调整
        Height = 714, ;
        Left = 284, ;
        Top = 35, ;
        Width = 771, ;
        Name = "Edit1"


    ADD OBJECT commandgroup1 AS commandgroup WITH ;
        ButtonCount = 6, ;
        Value = 1, ;
        Height = 30, ;
        Left = 1, ;
        Top = 2, ;
        Width = 154, ;
        Name = "Commandgroup1", ;
        Command1.Top = 2, ;
        Command1.Left = 3, ;
        Command1.Height = 25, ;
        Command1.Width = 25, ;
        Command1.Picture = "graphics\bitmaps\offctlbr\small\color\new.bmp", ;
        Command1.Caption = "", ;
        Command1.StatusBarText = "新建一个文件!", ;
        Command1.Alignment = 2, ;
        Command1.Name = "Command1", ;
        Command2.Top = 2, ;
        Command2.Left = 28, ;
        Command2.Height = 25, ;
        Command2.Width = 25, ;
        Command2.Picture = "graphics\bitmaps\offctlbr\small\color\open.bmp", ;
        Command2.Caption = "", ;
        Command2.StatusBarText = "打开一个文件!", ;
        Command2.Alignment = 2, ;
        Command2.Name = "Command2", ;
        Command3.Top = 2, ;
        Command3.Left = 53, ;
        Command3.Height = 25, ;
        Command3.Width = 25, ;
        Command3.Picture = "graphics\bitmaps\offctlbr\small\color\save.bmp", ;
        Command3.Caption = "", ;
        Command3.StatusBarText = "保存文件", ;
        Command3.Alignment = 2, ;
        Command3.Name = "Command3", ;
        Command4.Top = 2, ;
        Command4.Left = 78, ;
        Command4.Height = 25, ;
        Command4.Width = 25, ;
        Command4.Picture = "graphics\bitmaps\offctlbr\small\color\copy.bmp", ;
        Command4.Caption = "", ;
        Command4.StatusBarText = "复制选择的文字", ;
        Command4.Alignment = 2, ;
        Command4.Name = "Command4", ;
        Command5.Top = 2, ;
        Command5.Left = 103, ;
        Command5.Height = 25, ;
        Command5.Width = 25, ;
        Command5.Picture = "graphics\bitmaps\offctlbr\small\color\print.bmp", ;
        Command5.Caption = "", ;
        Command5.StatusBarText = "打印", ;
        Command5.Alignment = 2, ;
        Command5.Name = "Command5", ;
        Command6.Top = 2, ;
        Command6.Left = 128, ;
        Command6.Height = 25, ;
        Command6.Width = 25, ;
        Command6.Picture = "graphics\bitmaps\tlbr_w95\delete.bmp", ;
        Command6.Caption = "", ;
        Command6.StatusBarText = "删除当前文件", ;
        Command6.Name = "Command6"


    ADD OBJECT line1 AS line WITH ;
        Anchor = 10, ;
        Height = 0, ;
        Left = 1, ;
        Top = 32, ;
        Width = 1054, ;
        Name = "Line1"


    ADD OBJECT line2 AS line WITH ;
        Anchor = 10, ;
        Height = 0, ;
        Left = 1, ;
        Top = 33, ;
        Width = 1054, ;
        BorderColor = RGB(255,255,255), ;
        Name = "Line2"


    PROCEDURE Resize
        this.olecontrol1.Width=this.olecontrol3.Width
    ENDPROC


    PROCEDURE MouseMove &&当鼠标移动至2个控件之间,鼠标指针变成可调整边界的形状,进而动态调整控件的边界
        LPARAMETERS nButton, nShift, nXCoord, nYCoord
        IF nxcoord<this.edit1.Left+3 AND nxcoord>this.olecontrol3.Left+this.olecontrol3.Width-3
            this.MousePointer= 9
        *!*        IF nbutton=1 AND this.MousePointer=9
        *!*            this.olecontrol3.Width=nxcoord-this.olecontrol3.left
        *!*            this.olecontrol1.Width=this.olecontrol3.width
        *!*            x=this.edit1.left
        *!*            this.edit1.Left=this.olecontrol3.left+this.olecontrol3.width+3
        *!*            this.edit1.Width=this.edit1.Width+x-nxcoord-3
        *!*        ENDIF
        *!*    ELSE 
        *!*        this.MousePointer= 0 &&不能加这句,否则边框只能向右移,不能左移
        ENDIF

        IF this.MousePointer=9 AND nbutton=1 &&这两个条件顺序不一样居然效果不一样,我也是醉了。
            this.olecontrol3.Width=nxcoord-this.olecontrol3.left
            this.olecontrol1.Width=this.olecontrol3.width
            x=this.edit1.left
            nwidth=this.edit1.width 
            this.edit1.Left=this.olecontrol3.left+this.olecontrol3.width+3
            this.edit1.Width=nwidth+x-nxcoord-3
        ENDIF
    ENDPROC


    PROCEDURE olecontrol1.Refresh
        *** ActiveX 控件方法程序 ***
    ENDPROC


    PROCEDURE olecontrol1.Change
        *** ActiveX 控件事件 ***
    ENDPROC


    PROCEDURE olecontrol1.Init
    ENDPROC


    PROCEDURE olecontrol1.GetFirstVisible
        *** ActiveX 控件方法程序 ***
    ENDPROC


    PROCEDURE olecontrol3.MouseMove
        *** ActiveX 控件事件 ***
        LPARAMETERS button, shift, x, y
        thisform.MouseMove(button,shift,x,y)  &&向容器传递mousemove事件,冒泡。如果容器控件中还有控件,那么继续冒泡
    ENDPROC


    PROCEDURE olecontrol3.DblClick
        *** ActiveX 控件事件 ***
    ENDPROC


    PROCEDURE olecontrol3.Init
        this.Nodes.Add(,,"Root","我的电脑",,)
        DECLARE integer GetLogicalDriveStrings IN WIN32API integer,string@
        cstr=REPLICATE(CHR(0),40)
        n=getlogicaldrivestrings(40,@cstr)
        FOR i=1 TO n STEP 4
            this.nodes.Add(1,4,,SUBSTR(cstr,i,2),,)
        ENDFOR
        this.Nodes.Item(1).Expanded=.t.
    ENDPROC


    PROCEDURE olecontrol3.HitTest
        *** ActiveX 控件方法程序 ***
        LPARAMETERS x, y
    ENDPROC


    PROCEDURE edit1.MouseMove
        LPARAMETERS nButton, nShift, nXCoord, nYCoord

        thisform.MouseMove(nbutton,nshift,nxcoord,nycoord) &&向容器传递mousemove事件,冒泡。如果容器控件中还有控件,那么继续冒泡
    ENDPROC


ENDDEFINE
*
*-- EndDefine: form1
**************************************************


现在就可以动态调整edit控件的大小,以及treeview控件的大小了,所有控件都会随之调整大小。同理如果是grid控件,那么把cell,以及header的事件传递column,再把column的事件传递给grid,如果grid在container里面,或者pageframe里面,那么继续一级一级上传,直到传递给表单,然后我们在表单的事件中统一处理。

如果你们觉得这个方法有用,点个赞吧。。。


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

收到的鲜花
  • 厨师王德榜2022-11-17 09:11 送鲜花  1朵   附言:有价值的文章
搜索更多相关主题的帖子: 控件 this Left 容器 事件 
2022-11-16 22:11
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:858
专家分:1334
注 册:2021-10-13
收藏
得分:0 
刚才贴的代码有个小bug,form的mousemove方法要加一句话,代码如下:
程序代码:
    PROCEDURE MouseMove &&当鼠标移动至2个控件之间,鼠标指针变成可调整边界的形状,进而动态调整控件的边界
        LPARAMETERS nButton, nShift, nXCoord, nYCoord
        IF nxcoord<this.edit1.Left+3 AND nxcoord>this.olecontrol3.Left+this.olecontrol3.Width-3
            this.MousePointer= 9
        ENDIF

        IF this.MousePointer=9 AND nbutton=1 &&这两个条件顺序不一样居然效果不一样,我也是醉了。
            this.olecontrol3.Width=nxcoord-this.olecontrol3.left
            this.olecontrol1.Width=this.olecontrol3.width
            x=this.edit1.left
            nwidth=this.edit1.width 
            this.edit1.Left=this.olecontrol3.left+this.olecontrol3.width+3
            this.edit1.Width=nwidth+x-nxcoord-3
        ELSE
            this.mousepointer =0
        ENDIF
    ENDPROC
2022-11-16 22:31
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:858
专家分:1334
注 册:2021-10-13
收藏
得分:0 
回复 4楼 cssnet
上下拖动也是一样的,道理一样!
2022-11-17 11:36
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:858
专家分:1334
注 册:2021-10-13
收藏
得分:0 
回复 6楼 cssnet
应该可以做成类,设置2个参数,分别为2个相邻的object! 并不一定是由form来处理,看使用者需求,也可以由某个container控件来统一处理。
2022-11-17 11:44
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:858
专家分:1334
注 册:2021-10-13
收藏
得分:0 
不光是mousemove事件可以这样冒泡处理,click事件也经常有需求从控件传递给容器控件,比如commandgroup,只需在command控件的click事件中加一句,this.parent.click(),然后在commandgroup控件中,根据它的value值,对每个不同的command编写click事件。
2022-11-17 11:50
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:858
专家分:1334
注 册:2021-10-13
收藏
得分:0 
事实上,mousemove事件经常有会有小状况,不按套路走,我发上来的另一个目的是希望大家试用,看看有没有什么bug,以便反馈给我。

我今天发现偶尔会失灵,明明没有按下鼠标左键,系统会认为我按下了左键(不知道是不是我的鼠标问题),也就是,没有按下鼠标左键,居然有时候可以调整控件的大小。
2022-11-17 12:25
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:858
专家分:1334
注 册:2021-10-13
收藏
得分:0 
回复 11楼 cssnet
其实每个控件都有句柄,只是控件的句柄被隐藏了。我的意思让container控件来处理,意思是,可能不需要上升到form的程度。比如grid控件,我们把cell,header,column的mousemove事件传递给grid,这样就可以使用grid的gridhittest方法了,这里就没有需求将mousemove事件冒泡到form上。
2022-11-17 12:35
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:858
专家分:1334
注 册:2021-10-13
收藏
得分:0 
回复 10楼 吹水佬
我这样理解对不对,假设给form添加一个respond方法,参数为evalue,oobject,然后给控件的某个事件中写入以下代码:

thisform.respond(evalue,this)

这好像也是个好办法!
2022-11-17 12:45
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:858
专家分:1334
注 册:2021-10-13
收藏
得分:0 
回复 15楼 cssnet
就是那个K歌软件的字幕压制吗?成功了?
2022-11-17 12:50
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:858
专家分:1334
注 册:2021-10-13
收藏
得分:0 
回复 13楼 cssnet
呵呵,也是个好办法

刚试了以下,不行。因为我们要在鼠标左键按下的情况下,移动鼠标,才开始调节控件位置。没有按下鼠标的左键,移动鼠标,则不产生任何操作。按理我们松开鼠标,nbutton应该就会返回0,可事实上它的值居然还是1。。。所以系统误认为我们还在调整控件位置。

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

2022-11-17 12:52
快速回复:容器控件拦截容器内控件的方法
数据加载中...
 
   



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

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.032430 second(s), 10 queries.
Copyright©2004-2025, BC-CN.NET, All Rights Reserved