當您把專案的功能逐漸擴充之後,就會發現表單上安排的控制項愈來愈多,尤其是命令鈕愈來愈多,造成設計上的困擾。這時候大部分的應用軟體都會運用功能表,因為如果使用一大堆的命令鈕將會讓使用者無所適從。
功能表相當於分類的命令鈕,它可以執行使用者選取的命令。本章將介紹功能表的編輯、屬性、用法以及其他和功能表有關的課題。
功能表由「主選項」和「選項」所組成,以下圖的功能表為例,我們通常會稱呼它為「形狀功能表」,「形狀」就是主選項;在形狀功能表裡有「矩形」、「正方形」、「橢圓形」、「圓形」、「圓角矩形」、「圓角正方形」等選項。不過在
Visual Basic裡,不論是「形狀」這個主選項還是「矩形」這個選項或者其他的選項,都是一個功能表控制項(Menu控制項)。我們想要有下面的功能表該如何編輯呢?圖
12-1功能表範例雖然功能表也是一種控制項,但是功能表控制項和其它的控制項有些不同。在工具箱中並沒有功能表控制項的圖示可以選取,想要擁有功能表必須使用功能表編輯器編輯,要用功能表編輯器就點選
圖
12-2 功能表編輯器在功能表範例中,「形狀」是功能表控制項的標題
(Caption屬性),底下的選項如:「矩形」、「正方形」也都是功能表控制項的標題。功能表控制項並不會像其他的控制項會給一個預設的屬性值,所以在功能表編輯器中,「名稱」這一欄您一定要輸入,因為「名稱」就是Name屬性。我們就從「形狀」主選項開始輸入,首先在標題欄中輸入「形狀」,然後在名稱欄中輸入「
mnuShape」,這樣形狀主選項就完成了。輸入完畢按「下一個」鈕,就可以繼續輸入下一個功能表選項。接下來輸入「矩形」這個選項:在標題欄中輸入「矩形」,然後在名稱欄中輸入「
mnuRectangle」,由於「矩形」是屬於「形狀」底下的一個選項,所以必須按圖
12-3 功能表編輯過程按下「下一個」按鈕,就可以接著輸入「正方形」這個選項,然後輸入「橢圓形」這個選項,它們的
Caption屬性和Name屬性如下表所示。您可以按照下面的屬性表,使用功能表編輯器,輸入整個功能表,最後按下「確定」鈕,就可以在表單上看到圖12-1的功能表了。
整個功能表的屬性如下:
Name |
Caption |
|
功能表 Menu |
mnuShape | 形狀 |
功能表 Menu |
mnuRectangle | …矩形 |
功能表 Menu |
mnuSquare | …正方形 |
功能表 Menu |
mnuOval | …橢圓形 |
功能表 Menu |
mnuCircle | …圓形 |
功能表 Menu |
mnuRoundRectangle | …圓角矩形 |
功能表 Menu |
mnuRoundedSquare | …圓角正方形 |
功能表編輯器的按鈕
在「功能表編輯器」裡,有許多的按鈕,明瞭這些按鈕的用法,可以使您更方便的編輯功能表,底下說明個按鈕的功能:
當使用者點選某一個功能表時,就會產生
Click事件。本專案希望使用者選取「形狀」功能表內不同的選項時,表單上的形狀就跟著改變。Shape控制項的Shape就是如同功能表上所顯示的六種形狀,我們在使用者點選該形狀時,改變Shape控制項的Shape屬性,形狀就會改變了。使用者點選「形狀」、「矩形」時,產生
mnuRectangle_Click事件,此時我們要把Shape控制項(Name為shpItem)的形狀改為矩形,您可以將Shape屬性設定為0,或者像下列的程式碼使用內定的常數。Private Sub mnuRetangle_Click()
shpItem.Shape = vbShapeRectangle
End Sub
使用者點選「形狀」、「正方形」時,產生
mnuSquare_Click事件,此時我們要把Shape控制項的形狀改為正方形,您可以將Shape屬性設定為1,或者像下列的程式碼使用內定的常數。Private Sub mnuSquare_Click()
shpItem.Shape = vbShapeSquare
End Sub
使用者點選其他形狀時,都會產生
Click事件,我們也使用內定常數改變Shape控制項的形狀,程式碼如下:Private Sub mnuOval_Click()
shpItem.Shape = vbShapeOval
End Sub
Private Sub mnuCircle_Click()
shpItem.Shape = vbShapeCircle
End Sub
Private Sub mnuRoundedRectangle_Click()
shpItem.Shape = vbShapeRoundedRectangle
End Sub
Private Sub mnuRoundedSquare_Click()
shpItem.Shape = vbShapeRoundedSquare
End Sub
執行結果如下:
圖
12-4 執行結果 (Menu1.Vbp)認識子功能表
下一層級的功能表就是它的上一層級功能表的子功能表。功能表的選項裡,有一個往右的箭號時,當游標移動到這個選項時,就會出現下一層級的功能表,我們稱為子功能表。
圖
12-5 子功能表(Menu2.Vbp)在編輯功能表時,每一次按下
快捷鍵
請注意圖
12-5的功能表,主選項「顏色[C]」的C字底下有底線,表示使用者可以按下Alt + C 選取顏色功能表。「前景顏色[F]」的F字底下也有底線,表示使用者可以按下Alt + C 選取「顏色」後,再按下F鍵,就可以選取「前景顏色[F]」這個選項。我們稱這種按鍵方式為快捷鍵。要讓功能表具有快捷鍵,輸入標題時,就必須在快捷鍵的前方加上「
&」。例如您看到的「顏色[C]」,實際上的標題是「顏色[&C]」。而「前景顏色[F]」,實際上的標題是「前景顏色[&F]」。如果您需要顯示
&符號,而不是要使用快捷鍵,就要用兩個&。例如您輸入「&&HFFFFFF」,所顯示的標題是「&HFFFFFF」。使用者不會因為按下
Alt + F就直接選取「前景顏色」,因為Alt +快捷鍵只適用於最上層的功能表(主選項)。Menu
控制項陣列圖
12-5的子功能表部份,我們使用控制項陣列的方式設計,功能表的控制項陣列就是在索引(Index)項目裡填上數字。底下列出整個功能表的屬性,其中Name屬性欄中有括號者表示Index屬性。Name |
Caption |
|
功能表 Menu |
mnuColor | 顏色[&C] |
功能表 Menu |
mnuForeColor | …前景顏色[&F] |
功能表 Menu |
mnuColorItem(1) | ……藍色&&H800000 |
功能表 Menu |
mnuColorItem(2) | ……綠色&&H008000 |
功能表 Menu |
mnuColorItem(3) | ……青色&&H808000 |
功能表 Menu |
mnuBackColor | …背景顏色[&B] |
另外我們在表單的中央放置一個文字方塊
txtTest,並且希望使用者選取顏色選項時,文字方塊內的文字就改變顏色。如果不使用控制項陣列,就得撰寫三個功能表選項的Click事件。但是我們使用功能表控制項陣列,所以程式碼簡化如下:Private Sub mnuColorItem_Click(Index As Integer)
txtDisp.ForeColor = QBColor(Index)
End Sub
執行結果如下:
圖
12-6 執行結果(Menu2.Vbp)上一層功能表的控制
這些選項的上一層級的功能表
mnuForeColor,仍然具有Click事件,如果您要在顯示子功能表時也同時做一些事情的話,就可以利用上一層功能表的Click事件。如下的程式碼,您可以在開啟子功能表
(尚未選好)時,將文字方塊內的文字改為「前景顏色」。Private Sub mnuForeColor_Click()
txtDisp.Text = "
前景顏色"End Sub
執行結果:
圖
12-7執行結果 (Menu3.Vbp)前言
因為每一個功能表選項都是控制項,所以在屬性視窗中也可以找到這些物件,您可以在屬性視窗的物件清單中選取這些物件,然後修改它們的屬性。在功能表編輯器中也包括了這些屬性,但是用中文來表示,屬性視窗中則是使用英文,底下列出功能表編輯器中所用的中文和屬性視窗中的英文對照,以及屬性的說明:
功能表編輯器中 |
屬性視窗中 |
說明 |
標題 | Caption | 顯示給使用者點選的文字 |
名稱 | (Name) | 功能表的名字 |
索引 | Index | 有Index時表示是控制項陣列 |
核取式 | Checked | 為True時,功能表前面會有ˇ記號 |
啟用 | Enabled | 為False時,無法點選且呈現凹陷的字型 |
快速鍵 | ShortCut | 設定後,使用者可按下快速鍵直接選取功能表 |
可看見 | Visible | 為False時,該功能表將不可見 |
具視窗清單 | WindowList | 用在MDI表單,可以列出所有的視窗標題 |
分隔線
如果要產生如右的功能表分隔線,就在該功能表的
Caption屬性裡輸入「-」。一旦功能表為分隔線時,它就不能有子功能表,也不能是最上層的功能表。核取式
(Checked)我們經常可以在功能表前方看到如右圖的打ˇ的符號,此符號就是由
一般而言,如果功能表的
Checked屬性為True,表示該項功能表為被選取的狀態,實際上它只是一個提示符號。您可以根據需要,用程式碼針對Checked屬性詮釋其意義。另外,最上一層級的功能表不能使用Checked屬性。底下就示範用功能表
Checked屬性表達Label的三個特性:可見、邊框和立體的。功能表分為三個選項,使用者點選時,就將該選項的Checked屬性改變(本來為True就改成False,本來是False的,就改為True),然後依據是否打ˇ,改變標籤的屬性,例如:「可見」功能表選項打ˇ時,標籤的Visible屬性為True,「可見」功能表選項未打ˇ時,標籤的Visible屬性就設定為False。表單設計如下:圖
12-8 表單設計 (MenuCheck.Vbp)屬性值設定如下:
Name |
Caption |
|
功能表 Menu |
mnuLabel | 標籤的特性 |
功能表 Menu |
mnuVisible | …可見 |
功能表 Menu |
mnuBorder | …有邊框 |
功能表 Menu |
mnuSoild | …立體的 |
標籤 Label |
lblTest | 測試標籤 |
首先設計使用者點選「可見」選項時的程式:使用者點選「可見」時,要改變功能表前方的ˇ記號,我們只要使用
Not運算,這樣Checked屬性就會這一次是True,下一次是False了。當「可見」選項前面有ˇ記號時,我們將標籤設定為可見的,當「可見」選項前面沒有ˇ記號時,我們將標籤設定為不可見的,也就是標籤的Visible屬性相當於此功能表的Checked屬性,程式碼如下:Private Sub mnuVisible_Click()
mnuVisible.Checked = Not mnuVisible.Checked
lblTest.Visible = mnuVisible.Checked
End Sub
其次設計使用者點選「有邊框」選項時的程式:我們控制標籤的
BorderStyle屬性,當選項的前面打ˇ時,我們將標籤設定為具有邊框的,也就是BorderStyle=1,當選項的前面沒有ˇ時,我們將標籤設定為沒有邊框的,也就是BorderStyle =0,程式如下:Private Sub mnuBorder_Click()
mnuBorder.Checked = Not mnuBorder.Checked
If mnuBorder.Checked Then
lblTest.BorderStyle = 1
Else
lblTest.BorderStyle = 0
End If
End Sub
然後設計使用者點選「立體的」時的程式:我們控制標籤的
Apperance屬性,當選項的前面打ˇ時,我們將標籤設定為立體的,也就是Apperance=1,當選項的前面沒有ˇ時,我們將標籤設定為平面的,也就是Apperance=0,程式如下:Private Sub mnuSoild_Click()
mnuSoild.Checked = Not mnuSoild.Checked
If mnuSoild.Checked Then
lblTest.Appearance = 1
Else
lblTest.Appearance = 0
End If
End Sub
執行結果如下:
圖
12-9執行結果(MenuCheck.Vbp)Enabled
屬性本屬性是用來設定功能表選項是否啟用。當
Index
屬性填入
Index屬性,功能表就是控制項陣列了。使用功能表控制項陣列,可以簡化程式碼設計或者動態的增減功能表選項。使用Index屬性必須注意下列事項:Visible
屬性Visible屬性為決定功能表選項是否可見,當Visible屬性為False時,功能表選項就不可見,此時底下的功能表選項會依序遞補。如果該功能表選項的底下具有子功能表,當這個功能表選項的Visible屬性為False時,不但這個選項看不見,連它的子功能表也將無法看見。請看下圖的說明:
圖
12-10 功能表Visible屬性說明快速鍵
(ShortCut屬性)除了主選項,每一個功能表選項都可以設定快速鍵,當使用者按下快速鍵時,就會立即啟動該功能表的
Click事件。您可以在功能表編輯器中設定快速鍵,當功能表選項中設定好快速鍵時,在功能表選項的右方就會顯示按鍵的方式,如下圖所示:
圖
12-11 設定快速鍵使用快速鍵的注意事項如下:
當使用者按下滑鼠右鍵時,所呈現的浮動式的功能表我們稱為快顯功能表
要使用快顯功能表,還是要先編輯功能表,但是必須將此功能表的主選項的
Visible屬性設定為False,這樣才不會讓這個功能表顯示在表單上。當使用者按下滑鼠右鍵時,被按下鍵的控制項或表單會產生
MouseDown事件,我們可以在此事件中,確認使用者按下的滑鼠鈕是否為右鍵,若為右鍵,就用PopupMenu程序將功能表顯示出來,這樣就變成快顯功能表了。底下示範的專案,使用者可以按下滑鼠右鍵顯示快顯功能表,當使用者選取功能表上的選項後,就在表單上畫出選擇的圖畫。
我們使用功能表編輯器編輯一個最上層功能表為不可見的功能表,作為快顯功能表,並且在表單上安排
Image控制項陣列,用來存放圖片,由於這些圖片的背景是白色的,所以把表單的背景顏色也改為白色的。表單設計如下:圖
12-12表單設計(Popup.Vbp)屬性值設定如下:
Name |
Visible |
Picture |
|
影像 Image |
imgPic(0) | False | (點陣圖) |
影像 Image |
imgPic(1) | False | (點陣圖) |
影像 Image |
imgPic(2) | False | (點陣圖) |
在表單上看不到功能表,但是本專案具有功能表,它們的屬性值用功能表編輯器編輯如下:
Name |
Caption |
Visible |
|
功能表 Menu |
mnuPicture | 圖片 | False |
功能表 Menu |
mnuPicItem(0) | …魚 | True |
功能表 Menu |
mnuPicItem(1) | …青蛙 | True |
功能表 Menu |
mnuPicItem(2) | …猴子 | True |
為了在點選功能表選項後,畫出圖片的位置會在原先滑鼠右鍵按下的位置,所以在模組層次宣告底下的變數,紀錄滑鼠右鍵按下的位置:
Dim ClickX As Single, ClickY As Single
當表單產生
MouseDown事件時,表示滑鼠按鍵已經按下,此時我們就可以從Button參數得知按下的是左鍵還是右鍵,當Button=1時為左鍵,當Button=2時為右鍵。我們只要用
PopupMenu程序就可以將快顯功能表顯示出來,PopupMenu程序的第一個參數是功能表選項的Name,這個功能表選項必須要有下一層級的功能表選項。程式碼如下:Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
ClickX = X
ClickY = Y
If Button = 2 Then
PopupMenu mnuPicture
End If
End Sub
當使用者點選功能表選項後,就用
PaintPicture程序將圖片顯示在表單上。Private Sub mnupicItem_Click(Index As Integer)
PaintPicture imgPic(Index).Picture, ClickX, ClickY
End Sub
執行結果如下:
圖
12-13執行結果(Popup.Vbp)多個選項中只有一個成立
專案目標:表單上有一個以亂數出現的直線,製作一個功能表,讓使用者選取直線的樣式,而另一個功能表則可以選擇直線變化的快慢。
表單設計:表單上安排一個計時器控制項、
Line控制項和功能表。圖
12-14表單設計 (Demo1.Vbp)屬性設計:
Name |
Interval |
|
計時器 Timer |
tmrClock | 125 |
直線 Line |
linShow |
Name |
Caption |
Checked |
|
功能表 Menu |
mnuStyle | 形式 | |
功能表 Menu |
mnuStyleItem(0) | …透明 | False |
功能表 Menu |
mnuStyleItem(1) | …實線 | True |
功能表 Menu |
mnuStyleItem(2) | …破折線 | False |
功能表 Menu |
mnuStyleItem(3) | …點線 | False |
功能表 Menu |
mnuStyleItem(4) | …破折線-點線 | False |
功能表 Menu |
mnuStyleItem(5) | …破折線-點線-點線 | False |
功能表 Menu |
mnuSpeed | 速度 | |
功能表 Menu |
mnuSpeedItem(0) | …快速 | True |
功能表 Menu |
mnuSpeedItem(1) | …慢速 | False |
功能表 Menu |
mnuSpeedItem(2) | …靜止 | False |
程式設計:
Private Sub mnuStyleItem_Click(Index As Integer)
?
mnuStyleItem(linShow.BorderStyle).Checked = False?
linShow.BorderStyle = Index?
mnuStyleItem(linShow.BorderStyle).Checked = TrueEnd Sub
Private Sub mnuSpeedItem_Click(Index As Integer)
?
Static LastCheck As Integer?
mnuSpeedItem(LastCheck).Checked = FalseLastCheck = Index
mnuSpeedItem(LastCheck).Checked = True
‘
Select Case LastCheckCase 0
tmrShow.Interval = 125
Case 1
tmrShow.Interval = 250
Case 2
tmrShow.Interval = 0
End Select
End Sub
’
Private Sub tmrShow_Timer()
linShow.Y1 = Rnd * ScaleHeight
linShow.Y2 = Rnd * ScaleHeight
End Sub
程式解說:
BorderStyle的值 |
線條 |
說明 |
0 |
透明 | |
1 |
實線 | |
2 |
破折線 | |
3 |
點線 | |
4 |
破折線-點線 | |
5 |
破折線-點線-點線 | |
6 |
內實線 |
我們可以看到:
BorderStyle屬性為1或6時,顯示出來的直線是相同的。在功能表設計時就省略了「內實線」這個選項。Line控制項的BorderStyle的內定值為1(實線),所以在屬性設定時,就將功能表選項「實線」的Checked屬性設定為True。當使用者點選樣式的功能表選項時,先將原先的ˇ符號清除。執行結果:
圖
12-15執行結果(Demo1.Vbp)可以增減的功能表
專案目標:示範一個可以增加或減少功能表選項的專案。
表單設計:安排
1個文字方塊做為輸入之用,安排1個標籤做為輸出之用。圖
12- 16表單設計(Demo2.Vbp)
屬性設定:
Name |
Caption |
Text |
|
文字方塊 TextBox |
txtMenu | ||
標籤 Label |
lblMsg |
Name |
Caption |
Enabled |
Visible |
|
功能表 Menu |
mnuAdd | 增加 | True | True |
功能表 Menu |
mnuDel | 減少 | False | True |
功能表 Menu |
mnuDefine | 自訂 | True | False |
功能表 Menu |
mnuUser | … | True | True |
程式設計:
?
Dim MenuCount As Integer
Private Sub mnuAdd_Click()
?
If txtMenu.Text <> "" Then?
If MenuCount = 0 ThenmnuDel.Enabled = True
mnuDefine.Visible = True
Else
?
Load mnuUser(MenuCount)End If
?
mnuUser(MenuCount).Caption = txtMenu.TextMenuCount = MenuCount + 1
End If
End Sub
Private Sub mnuDel_Click()
‘
MenuCount = MenuCount - 1’
If MenuCount = 0 ThenmnuDel.Enabled = False
mnuDefine.Visible = False
Else
“
Unload mnuUser(MenuCount)End If
End Sub
”
Private Sub mnuUser_Click(Index As Integer)
lblMsg.Caption = "
您現在選取的是[" & mnuUser(Index).Caption & "]"End Sub
程式解說:
執行結果:
圖
12-17 執行結果(Demo2.Vbp)兩種不同的快顯功能表
專案目標:在一個表單裡,您可以根據目前狀態的不同,以動態的方式改變快顯功能表的選項,也可以製作多個功能表,然後根據需要顯示不同的快顯功能表。本專案示範一個顯示圖片的程式,當滑鼠在圖片之外點選時,顯示「新增圖片」功能表,可以增加新的圖片,當滑鼠在圖片之內點選時,顯示「修改圖片」功能表,可以「刪除」或更換圖片。
表單設計:表單的
BackColor屬性設定為白色,並且安排三個影像放置要顯示的圖片,這些圖片事先處理成背景通透的,存放於光碟的Ch14\Pic目錄裡。安排一個imgClick控制項,設定其Index屬性為0,這樣就可以動態載入此控制項,已做為顯示之用。設計兩組功能表,每一個功能表主選項的Visible都設定成False,這樣就不會顯示在表單的上方。圖
12- 17表單設計(Demo3.Vbp)屬性設定:
Name |
Visible |
Picture |
|
影像 Image |
imgPic(0)~imgPic(2) | False | (點陣圖) |
影像 Image |
imgClick(0) | False | (無) |
Name |
Caption |
Visible |
|
功能表 Menu |
mnuAddPicture | 增加圖片 | False |
功能表 Menu |
mnuPicItem(0) | …魚 | True |
功能表 Menu |
mnuPicItem(1) | …青蛙 | True |
功能表 Menu |
mnuPicItem(2) | …猴子 | True |
功能表 Menu |
mnuModify | 修改圖片 | False |
功能表 Menu |
mnuDel | 刪除 | True |
功能表 Menu |
mnuPicItem(0) | …魚 | True |
功能表 Menu |
mnuPicItem(1) | …青蛙 | True |
功能表 Menu |
mnuPicItem(2) | …猴子 | True |
程式設計:
?
Dim ClickX As Single, ClickY As Single
Dim ImageCount As Integer
Dim ImageIndex As Integer
?
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
ClickX = X
ClickY = Y
If Button = 2 Then
PopupMenu mnuAddPicture
End If
End Sub
?
Private Sub mnupicItem_Click(Index As Integer)
ImageCount = ImageCount + 1
Load imgClick(ImageCount)
imgClick(ImageCount).Move ClickX, ClickY
imgClick(ImageCount).Picture = imgPic(Index)
imgClick(ImageCount).Visible = True
imgClick(ImageCount).Tag = Index
imgClick(ImageCount).ZOrder 0
End Sub
?
Private Sub imgClick_MouseDown(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = 2 Then
ImageIndex = Index
mnuChangeItem(0).Enabled = True
mnuChangeItem(1).Enabled = True
mnuChangeItem(2).Enabled = True
mnuChangeItem(imgClick(Index).Tag).Enabled = False
PopupMenu mnuModify
End If
End Sub
?
Private Sub mnuChangeItem_Click(Index As Integer)
imgClick(ImageIndex).Picture = imgPic(Index)
imgClick(ImageIndex).Tag = Index
End Sub
‘
Private Sub mnuDel_Click()
imgClick(ImageIndex).Visible = False
End Sub
程式解說:
執行結果:
圖
12-18 執行結果(Demo3.Vbp)習題