VB6.0自制Line控件時(shí)完成X1,Y1,X2,Y2屬性
發(fā)表時(shí)間:2024-02-17 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]Line控件本來(lái)是最簡(jiǎn)單的一個(gè)控件,但它太簡(jiǎn)單了,以至于不提供我們想要的一些事件,為了增強(qiáng)它的功能,我自己制作了一個(gè)Line控件,還給她取名叫作MLine控件。制作控件的方法請(qǐng)參看"MSDN - Visual Basic 文檔 - 使用Visual Basic -部件工具指南 - 創(chuàng)建A...
Line控件本來(lái)是最簡(jiǎn)單的一個(gè)控件,但它太簡(jiǎn)單了,以至于不提供我們想要的一些事件,為了增強(qiáng)它的功能,我自己制作了一個(gè)Line控件,還
給她取名叫作MLine控件。
制作控件的方法請(qǐng)參看"MSDN - Visual Basic 文檔 - 使用Visual Basic -部件工具指南 - 創(chuàng)建ActiveX部件"中的"創(chuàng)建一個(gè)ActiveX控件"和"
建立ActiveX控件"部分。
VB自帶的Line控件有X1,X2,Y1,Y2四個(gè)屬性,沒有Left,Top,Width,Height這四個(gè)屬性,通過調(diào)整X1-Y2四個(gè)屬性的值,來(lái)改變線條的位置和形狀
。但,我們的Mline控件中只有LTWH這四個(gè)屬性,所以MLine控件的關(guān)鍵在于如何把LTWH四個(gè)屬性跟X1-Y2四個(gè)屬性聯(lián)系起來(lái)。
很顯然,如果MLine控件中的線條是從左上角到右下角的話,那么:
A1=Left : B1=Top : A2=Left+Width : B2=Top+Height
這里我用(A1,B1)表示左上角的坐標(biāo),(A2,B2)表示右上角的坐標(biāo),這樣我就可以通過A1-B2來(lái)確定控件的區(qū)域了,但并不能確定直線的形狀,也
就是說直線是撇傾斜還是捺傾斜,通過A1-B2無(wú)法確定,我們需要一個(gè)標(biāo)志變量來(lái)記錄這個(gè)傾斜值,下面會(huì)說到。
好了,A1-B2顯然和LTWH是一一對(duì)應(yīng)的,我們可以寫出:
Left=A1 : Top=B1 : Wdith=A2-A1 : Height=B2-B1
A1=Min(X1,X2) : B1=Min(Y1,Y2) : A2=Max(X1,X2) : B2=Max(Y1,Y2)
通過上面的關(guān)系,我們把X1-Y2和LTWH聯(lián)系起來(lái)了。
那么你去做吧,基本上這個(gè)線條可以畫出來(lái),但不會(huì)太精確,在線條接近水平或垂直的時(shí)候就會(huì)有誤差了,出現(xiàn)誤差的原因是,控件有一個(gè)最
小寬度和最小高度!你可以隨便建立一個(gè)EXE工程觀察一下常用的控件,他們的Height/Width最小只能設(shè)置到15或者更大一些,而UserControl
,也就是我們的控件,其Height/Width最小只能設(shè)置到30,所以如果沒有考慮到這個(gè)因素,做出來(lái)的MLine控件總會(huì)出現(xiàn)誤差的,如果你把做出
來(lái)的MLine控件,以(X1,Y1)為圓心,讓(X2,Y2)繞著它畫圓,你會(huì)發(fā)現(xiàn)線條的一些細(xì)微變化,這種變化是不能容忍的。
所以MLine控件的重點(diǎn)是要理解這個(gè)控件的真實(shí)形狀,它不僅僅是一個(gè)長(zhǎng)方形的區(qū)域內(nèi)做一條對(duì)角線,而是這樣的一個(gè)樣子:
在它的區(qū)域當(dāng)中,有一片冗余區(qū)域,我們不能在這里畫線,理由是這個(gè)冗余區(qū)域正是這個(gè)控件的最小區(qū)域。這個(gè)冗余區(qū)域我設(shè)置它為一個(gè)空心
矩形,它和MLine控件的整個(gè)區(qū)域是重合的,它中間的空心區(qū)域才是我們畫線的地方?招膮^(qū)域應(yīng)該是由最小寬度和最小高度決定的,讓MinWid
th表示最小寬度,MinHeight表示最小高度,那么空心區(qū)域和控件區(qū)域的左邊界=MinWidth/2,右邊界=MinWidth/2,上邊界=MinHeight/2,下邊
界=MinHeight/2,你應(yīng)該可以想象出來(lái)這個(gè)樣子。
好了,這就是MLine控件的重點(diǎn)所在,我們?cè)賮?lái)調(diào)整一下X1-Y2和LTWH之間的關(guān)系,當(dāng)然我還是先用A1-B2來(lái)解釋,這樣清楚一點(diǎn):
A1=Extender.Left+MinWidth/2
B1=Extender.Top+MinHeight/2
A2=Extender.Left+Extender.Width-MinWidth/2
B2=Extender.Top+Extender.Height-MinHeight/2
A2=A1+Extender.Width-MinWidth
B2=B1+Extender.Height-MinHeight
Extender.Left=A1-MinWidth/2
Extender.Top=B1-MinHeigth/2
Extender.Width=A2-A1+MinWidth
Extender.Height=B2-B1+MinHeight
其中A1=Min(X1,X2)
B1=Min(Y1,Y2)
A2=Max(X1,X2)
B2=Max(Y1,Y2)
看到了嗎?A1-B2和LTWH建立了一一對(duì)應(yīng)的關(guān)系,而通過Min/Max方法的計(jì)算,我們也可以使X1-Y2和LTWH建立對(duì)應(yīng)的關(guān)系,但不是一一對(duì)應(yīng)的。
為什么呢?這里我們需要一個(gè)標(biāo)志變量blnK,它表示直線的傾斜方向,也就是說撇傾斜或者捺傾斜,通過blnK,我們才可以使X1-Y2和LTWH建立
一一對(duì)應(yīng)的關(guān)系,也就是說,我們既可以改變LTWH來(lái)引起X1-Y2的變化,也可以通過改變X1-Y2來(lái)改變LTWH,這樣我們就得到了屬性X1-Y2的Get/
Let方法如下:
(實(shí)際應(yīng)用中,我沒有采用blnK來(lái)記錄傾斜方向,而是用PosX1和PosY1來(lái)記錄X1,Y1在四個(gè)角的位置)
'客戶區(qū)位置X1
Public Property Get X1() As Single
If PosX1 = LS_LEFT Then
X1 = Extender.Left + MinWidth / 2
Else
X1 = Extender.Left + Extender.Width - MinWidth / 2
End If
End Property
Public Property Let X1(ByVal NewX1 As Single)
Dim OldX2 As Single
OldX2 = X2
If NewX1 > OldX2 Then
'新的X1在X2右邊
PosX1 = LS_RIGHT
Extender.Left = OldX2 - MinWidth / 2
Extender.Width = NewX1 - OldX2 + MinWidth
Else
'新的X1在X2左邊
PosX1 = LS_LEFT
Extender.Left = NewX1 - MinWidth / 2
Extender.Width = OldX2 - NewX1 + MinWidth
End If
PropertyChanged "X1"
End Property
X2,Y1,Y2的屬性方法與此類似,不再贅述。
在Paint事件中我們使用Line方法來(lái)畫線,但要記住不是從X1,Y1畫到X2,Y2,而是從X1-Extener.Left,Y-Extender.Top到X2-Extender.Left,Y2-
Extender.Top畫線。
值得注意的是,有人可能會(huì)不明白屬性和屬性方法Get/Let之間的關(guān)系,因此而造成許多的誤會(huì),應(yīng)該明白X1-Y2的值是保存在Get方法中的,每
次讀取X1-Y2都會(huì)調(diào)用Get方法來(lái)求得其值,注意!是求得!所以你也可以認(rèn)為并沒有X1-Y2這四個(gè)變量。而每次設(shè)置X1-Y2,其實(shí)就是在設(shè)置LTW
H和PosX1、PosY1,希望你能對(duì)此明了,有的人會(huì)在Resize/Paint事件中去設(shè)置X1-Y2,然后在X1-Y2中又設(shè)置LTWH,這樣就又會(huì)引起Resize/Pai
nt事件,中間出現(xiàn)遞歸調(diào)用,雖然通過設(shè)置標(biāo)志變量的方法可以防止無(wú)限遞歸,但那樣就復(fù)雜多了,很遺憾地說,我一開始就是這樣做的。
對(duì)于X1-Y2的Let方法的調(diào)用,只有三種情況,第一種情況是ReadProperties,這時(shí)會(huì)用Form中保存的X1-Y2來(lái)設(shè)置X1-Y2的值;第二種情況就是
開發(fā)者,第三種情況可能會(huì)是使用者。
要明白,每次LTWH的變化都會(huì)直接引起X1-Y2的變化,知道了這一點(diǎn),就不會(huì)再去Resize/Paint事件中跟蹤LTWH的變化了。