大家對Windows的菜單非常熟悉,這種統壹格式的灰色菜單有時並不能滿足壹些應用程序的要求,特別是那些對界面要求比較高的多媒體設計。問題是,VC、VB中提供的菜單編輯器並不支持圖形菜單功能!不要著急,我們馬上自己來開發壹個!
創建 menus工程
首先打開VB6.0,在新建工程中選擇Activex 控件, 這時設計窗口出現壹個類似form表單的界面 這就是妳的ocx設計器,缺省名為UserControl1。
1. 在"工程"菜單上單擊"Project1 屬性",打開"工程屬性"對話框。選擇"通用"選項卡,將工程名稱改為menus
2. 在UserControl1 的"屬性"窗口中點擊"名稱" 屬性並且把用戶控件名改為menuControl
妳可能註意到, menuControl的"屬性"窗口和標準的VB的form"屬性"窗口既類似又有不同。記住,現在我們設計的是ocx控件,而不是VB中的form!
添加 Test 工程
由於 .ocx 工程不能獨立運行,所以我們將添加壹個Test工程。在同壹工程組中裝入設計工程(menus工程)和測試工程(Test工程)將十分有利於調試運行中的部件。
1.在"文件"菜單上單擊"添加工程"以打開"添加工程"對話框。
註意: 不要單擊"打開工程" 或"新建工程",因為這樣會關閉控件工程。
2.雙擊"Standard EXE"圖標以添加普通的 .exe 工程(即我們的Test工程)。
該新工程立即成為這個工程組的"啟動"工程。"工程資源管理器"窗口以黑體名字的顯示來標識"啟動"工程。
註意: ActiveX 控件工程是不能作為啟動工程的。
3. 在"文件"菜單上單擊"保存工程組"用以保存測試工程和工程組。
& ocx代碼設計 &
1. 在menus工程的module模塊中增加如下代碼:
Type menuRect '創建用戶自定義類型
left As Integer
top As Integer
right As Integer
bottom As Integer
End Type
2. 在控件設計窗口中加入壹個picturebox控件,取名為bmpmenu。
在bmpmenu中加入另壹個picturebox控件,取名為menuitem。
註意: menuitem是bmpmenu的子控件。並且,這兩個picturebox的
AutoSize屬性皆設為True,BorderStyle屬性皆設為None。
3. 在控件設計窗口中的General->Declarations中增加如下代碼:
Public g_selectedItem As String
Dim g_fileName As String '菜單文件名
Dim g_height As Integer 'ocx控件的高度
Dim g_width As Integer 'ocx控件的寬度
Dim bmpRects() As menuRect 'bmpRects()用來記錄所有菜單項的位置
Dim currentItemNumbers As Integer
Dim currentItemNumber As Integer
Public Event MENUITEMDOWN()
註意: MENUITEMDOWN是我們添加到控件中的壹個事件,它的詳細作用我們稍後會具體介紹。
4. 為我們的菜單控件添加兩個屬性: childs 和 BmpName
childs屬性表示菜單控件的菜單項數目, BmpName屬性表示菜單控件的菜單文件名
首先,打開menuControl的代碼窗口。在"工具"菜單上點擊"添加過程"打開"添加過程"對話框。在"名稱"框輸入名字childs。單擊"屬性"和"公***的"後再單擊"確定"。
妳將看到如下的代碼:
Public Property Get childs() As Variant
End Property
Public Property Let del1(ByVal vNewValue As Variant)
End Property
然後,在代碼窗口更改我們新創建的屬性過程(修改的部份以黑體表示):
Public Property Get childs() As Integer
childs = currentItemNumbers
End Property
Public Property Let childs(ByVal vNewValue As Integer)
currentItemNumbers = vNewValue
PropertyChanged "childs"
PopAndResize ' 這是壹個子過程
End Property
當妳對childs屬性賦新值時均執行 Property Let 過程, 而當妳對childs屬性檢索該屬性值時均執行 Property Get 過程。
對BmpName屬性也同樣處理,它的代碼部份如下:
Public Property Get BmpName() As String
BmpName = g_fileName
End Property
Public Property Let BmpName(ByVal vNewValue As String)
g_fileName = vNewValue
PropertyChanged "BmpName"
PopAndResize
End Property
5. 為了初始化ocx控件,在 UserControl_InitProperties 事件過程中
添加如下代碼:
Private Sub UserControl_InitProperties()
BmpName = ""
childs = 0
End Sub
在UserControl_Resize 事件過程中添加如下代碼:
Private Sub UserControl_Resize()
If g_height < 20 And g_width < 20 Then '決定設計狀態時的控件大小
UserControl.Height = 300
UserControl.Width = 300
Else
UserControl.Height = g_height '決定運行狀態時的控件大小
UserControl.Width = g_width
End If
End Sub
註意: ocx控件設計涉及到許多重要概念,大家必須親自實踐才能真正融會貫通,
下面簡單地介紹壹下ocx的事件過程設計。
與壹般的可編程對象不同,ocx控件同時具有設計時和運行時的兩種行為。 即開發者在設計時把壹個控件放入窗體時,控件中的壹些代碼將會執行。
例如,把我們設計的menu控件放入test工程的窗體時, 放置在 UserControl_Resize 事件過程中的代碼將會執行;當test工程進入運行狀態時, UserControl_Resize事件過程中的代碼也會執行。所以,我在UserControl_Resize過程中使用If...Else語句來決定menu控件分別在設計狀態和運行狀態時的尺寸大小。
6. 好了,我們的ocx控件馬上就要完工了,再堅持壹下!(ocx確實有點難度,不過它可是代表最新的技術設計概念哦!)
把下面的sub過程加入ocx設計器的代碼部分:
Sub popbmpMenu(xposition As Integer, yposition As Integer, itemNumbers As_ Integer, fileName As String)
ReDim bmpRects(itemNumbers)
bmpmenu.Visible = False
g_fileName = fileName
bmpmenu.Picture = LoadPicture(g_fileName + ".bmp")
menuitem.Visible = False
currentItemNumbers = itemNumbers
itemHeight = Int(bmpmenu.Height / itemNumbers)
For i = 0 To itemNumbers - 1
bmpRects(i).left = xposition
bmpRects(i).right = bmpmenu.Width
If i = 0 Then
bmpRects(i).top = yposition
Else
bmpRects(i).top = bmpRects(i - 1).bottom
End If
bmpRects(i).bottom = itemHeight * (i + 1)
Next i
bmpmenu.ZOrder 0
bmpmenu.left = 0
bmpmenu.top = 0
bmpmenu.Visible = True
g_height = bmpmenu.Height ' 菜單位圖文件決定了ocx控件的大小
g_width = bmpmenu.Width
End Sub
Sub PopAndResize()
menuitem.Visible = False
If childs > 0 And BmpName <> "" Then
Call popbmpMenu(0, 0, childs, BmpName)
End If
UserControl.Height = g_height ' 調整ocx控件的大小
UserControl.Width = g_width
End Sub
Private Sub GetSelectedItem() '判斷哪個菜單項被選中
g_selectedItem = right(g_fileName, 2) + "-" + LTrim(Str(currentItemNumber))
End Sub
最後是兩個picturebox上的壹些代碼:
Private Sub bmpmenu_MouseMove(Button As Integer, Shift As Integer, X As Single, _
Y As Single)
menuitem.Visible = False
For i = 0 To currentItemNumbers - 1
If X > bmpRects(i).left And Y > bmpRects(i).top And X < bmpRects(i).right _
And Y < bmpRects(i).bottom Then
currentItemNumber = 0
menuitem.Picture = LoadPicture(g_fileName + "-" + LTrim(Str(i + 1)) + ".bmp")
currentItemNumber = i + 1
menuitem.Move bmpRects(i).left , bmpRects(i).top
menuitem.Visible = True
Exit Sub
End If
Next i
End Sub
Private Sub menuitem_MouseDown(Button As Integer, Shift As Integer, X As Single, _
Y As Single)
GetSelectedItem
menuitem.Visible = False
'啟動MENUITEMDOWN事件,此事件的執行代碼不寫在ocx
'中,而是寫在調用此ocx的應用中。
RaiseEvent MENUITEMDOWN
End Sub
& 測試ocx控件 &
OK, 我們的ocx終於完成了!下面我們可以來測試壹下了!
制作壹張菜單bmp文件,它的名字為c2.bmp,***有5個菜單項。
制作5個菜單項的激活狀態位圖,取名為c2-1.bmp,c2-2.bmp,c2-3.bmp,c2-4.bmp,c2-5.bmp
將這些位圖文件存放在和工程組同層的文件夾中。
關閉ocx設計器窗口,打開ocxTest窗口,我們發現在ToolBox工具欄中多了壹個新的控件,這就是我們所設計的menuControl。在ocxTest窗口上放置壹個menuControl控件,然後在代碼窗口中填入以下程序:
Private Sub Form_Click()
menuControl1.BmpName = App.Path + "\c2"
menuControl1.childs = 5
menuControl1.Visible = True
End Sub
Private Sub Form_Load()
menuControl1.Visible = False
End Sub
Private Sub menuControl1_MENUITEMDOWN()
menuControl1.Visible = False
Dim selectMenu As Integer
selectMenu = Val(Trim(Mid(menuControl1.g_selectedItem, 4, 2)))
Select Case selectMenu
Case 1
'第壹個菜單項被選中
Case 2
'第二個菜單項被選中
Case 3
'第三個菜單項被選中
Case 4
'第四個菜單項被選中
Case 5
'第五個菜單項被選中
End Select
End Sub
怎麽樣?調用夠簡單的吧!這正是微軟提出的組件設計的優勢。不錯,ocx設計的確有些難度,然而壹旦設計好,它的調用是十分方便的。ocx的可重用率和易維護性是值得我們在設計時多花些時間的,更重要的是,在軟件設計越來越復雜的今天,采用正確的組件設計思想是尤為關鍵的!
& 編譯ocx &
如果壹切順利的話,我們就可以編譯ocx了。
1. 在"工程資源管理器"窗口單擊"menus"以選擇該工程。
2. 在"文件"菜單上單擊"生成 menuControl.ocx" 。
註意: 如果妳需要妳的ocx控件具有許可證,可按如下操作
在"工程"菜單上,點擊"menus 屬性"打開"工程屬性"對話框。選擇"通用"選卡,選定"要求許可證關鍵字",然後單擊"確定"。
這樣,即使有人將妳的ocx拷貝了去,他也無法使用!妳就不必擔心妳的心血被人侵犯嘍!
& 使用ocx控件 &
由於我們的ocx已經編譯成功,所以現在就可以像使用系統中的標準控件壹樣來調用我們的menuControl.ocx了。
退出設計時的工程組,新建壹個VB的標準工程,在"工程"菜單上單擊"部件",在 Controls 的選項卡上,復選"menus"後再單擊"確定"。現在menuControl控件和Label,TextBox等控件就壹樣被對待處理了,只不過menuControl是我們自己設計的!
菜單的圖形文件起名有壹定規則,大家只要看壹下程序就明白了。當然,讀者朋友們也可以按自己喜歡的方式來處理文件名。
& 後記 &
ocx控件設計還涉及到許多方方面面,由於篇幅有限,這裏就不詳述了(其實,大家能堅持到這裏就夠有耐心了! (-_-) )。menuControl還有不少地方需要改進,這就待以後再慢慢完善了。