Trả lời :
Để giải quyết việc tạo menu động như bạn yêu cầu, cần trang bị 2 kiến thức chính:
- Kiến thức về các hàm API Windows để quản lý menu như GetMenu(), DeleteMenu(), InsertMenuItem(), CreatePopupMenu()... Thông tin cụ thể và chi tiết về cách dùng các hàm này được trình bày trong CD MSDN của Microsoft.
- Kiến thức về việc truy xuất dữ liệu trong database, thí dụ kiến thức về việc dùng các đối tượng trong thư viện cấp cao ADO để truy xuất database.
Ý tưởng của việc tạo menu động từ thông tin trong database có thể tóm tắt như sau:
- Tạo 1 menu trống cho Form ứng dụng.
- Đọc vào danh sách các record của bảng menuchinh theo thứ tự của field vitri (phải có giá trị liên tục từ 0 trở lên).
- Lặp thêm từng menu pop-up theo thông tin của record trong danh sách, đọc vào danh sách các record của bảng menucap2 có cùng giá trị ID như phần tử menu chính hiện hành, lặp thêm từng option theo thông tin của record trong danh sách.
Qui trình viết ứng dụng tạo menu động cụ thể sẽ phụ thuộc nhiều vào môi trường lập trình, vào ngôn ngữ lập trình được dùng. Ở đây chúng tôi xin giới thiệu qui trình điển hình để viết ứng dụng tạo menu động theo yêu cầu của bạn bằng môi trường VB 6.0. Giả sử bạn đã tạo sẵn 2 bảng menuchinh và menucap2 với nội dung theo yêu cầu và chứa chúng trong file Access c:\YourDB.mdb:
1. Chạy VB 6.0, tạo Project ứng dụng mới theo dạng "Standard EXE". Đây là Project quản lý ứng dụng đơn giản nhất, có 1 Form trống ban đầu.
2. Sau khi Form ứng dụng hiển thị, chọn menu Tool.Menu Editor để mở cửa sổ soạn menu cho Form. Hãy tạo 1 menubar chỉ chứa 1 menu ban đầu (thí dụ Caption=File, Name=mnuFile) rồi đóng cửa sổ soạn menu lại. Mục đích của bước này là tạo 1 menu tĩnh ban đầu cho Form chỉ chứa 1 menu pop-up trống. Việc hiệu chỉnh thông tin về menu sẽ được lập trình động trong bước kế tiếp.
3. Chọn menu Project.References để hiển thị cửa sổ References, duyệt tìm và chọn mục "Microsoft ActiveX Data Objects 2.x Library" và chọn button Ok để thêm các đối tượng ADO của thư viện này vào Project ứng dụng.
4. Chọn menu View.Code để mở cửa sổ soạn code của chương trình rồi nhập đoạn chương trình sau đây:
'khai báo các hàm API cần dùng
Private Declare Function GetMenu Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function CreatePopupMenu Lib "user32" () As Long
Private Declare Function DeleteMenu Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long
Private Declare Function InsertMenuItem Lib "user32" Alias "InsertMenuItemA" (ByVal hMenu As Long, ByVal un As Long, ByVal bool As Boolean, ByRef lpcMenuItemInfo As MENUITEMINFO) As Long
'khai báo kiểu cần dùng
Private Type MENUITEMINFO
cbSize As Long
fMask As Long
fType As Long
fState As Long
wID As Long
hSubMenu As Long
hbmpChecked As Long
hbmpUnchecked As Long
dwItemData As Long
dwTypeData As String
cch As Long
End Type
'khai báo hằng cần dùng
Const MF_STRING = &H0
Const MIIM_STRING = &H40
Const MIIM_SUBMENU = &H4
Const MIIM_ID = &H2
Const MIIM_TYPE = &H10
Const MIIM_DATA = &H20
Const MF_BYPOSITION = &H400
'Khai báo các biến cần dùng
Dim MII As MENUITEMINFO
Dim Connection1 As ADODB.Connection
Dim Command1 As ADODB.Command
Dim RecordSet1 As ADODB.Recordset
Dim RecordSet2 As ADODB.Recordset
'thủ tục khởi động Form ứng dụng
Private Sub Form_Load()
Dim hMenu As Long
Dim hSubMenu As Long
'xác định menubar của Form
hMenu = GetMenu(Me.hwnd)
'xóa menu pop-up đã có
kq = DeleteMenu(hMenu, 0, MF_BYPOSITION)
Dim MyConString As String
MyConString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source = c:\YourDB.mdb"
'Tạo connection tới database
Set Connection1 = New ADODB.Connection
Connection1.Open MyConString
'Tạo command làm việc với database
Set Command1 = New ADODB.Command
Command1.ActiveConnection = Connection1
'tạo danh sách menu cấp 1 theo thứ tự vị trí
Command1.CommandText = "select * from menuchinh order by vitri ASC"
Set RecordSet1 = Command1.Execute()
'lặp thêm động từng menu pop-up trong danh sách
While Not RecordSet1.EOF()
'xây dựng thông tin về menu pop-up cần tạo
MII.cbSize = Len(MII)
MII.dwTypeData = RecordSet1.Fields("tieudechinh").Value
MII.cch = LenB(MII.dwTypeData)
MII.hSubMenu = CreatePopupMenu()
MII.fMask = MIIM_ID Or MIIM_STRING Or MIIM_SUBMENU
'thêm menu pop-up này
ret = InsertMenuItem(hMenu, RecordSet1.Fields("vitri").Value, MF_BYPOSITION, MII)
hSubMenu = MII.hSubMenu
'tạo danh sách menu cấp 2 của menu pop-up hiện hành theo thứ tự vị trí
Command1.CommandText = "select * from menucap2 where ID=" & RecordSet1.Fields("ID").Value & " order by vitri ASC"
Set RecordSet2 = Command1.Execute()
'lặp thêm động từng menu item trong danh sách
While Not RecordSet2.EOF()
'xây dựng thông tin về menu item cần tạo
MII.cbSize = Len(MII)
MII.dwTypeData = RecordSet2.Fields("tieudephu").Value
MII.cch = LenB(MII.dwTypeData)
MII.fMask = MIIM_STRING
'thêm menu item này
ret = InsertMenuItem(hSubMenu, RecordSet2.Fields("vitri").Value, MF_BYPOSITION, MII)
'di chuyển đến item kế tiếp
RecordSet2.MoveNext
Wend
'di chuyển đến menu pop-up kế tiếp
RecordSet1.MoveNext
Wend
'đóng các đối tượng đã dùng lại
RecordSet1.Close
RecordSet2.Close
Connection1.Close
End Sub
5. Chạy chương trình và kiểm tra kết quả xem menu được tạo ra đúng theo đặc tả trong database hay không? Lưu ý rằng đoạn code trên mới chỉ tạo động được menubar chứ chưa liên kết thủ tục xử lý sự kiện cho từng option menu.