Wstęp
W poprzednim poście skupiłem się na pokazaniu jak zbudować menu bez panelu przełączania, tworząc ze środowiska Accessowego coś na styl MDI. Oczywiście to był tylko wstęp do dalszych rozważań na temat jak to wykorzystać dalej.
Ja najczęściej tworzę tabelę w której odwzorowuje strukturę menu, jak i zapisuje informacje niezbędne do wykonania odpowiedniej akcji po kliknięciu na danym elemencie.
Tworzenie konfiguracji
Dla przypomnienia, struktura przykładowa menu wygląda tak:
menu1 |- menu1 opcja1 |- menu1 opcja2 menu2 |- menu2 opcja1 |- menu2 opcja2
Zróbmy zatem jej odwzorowanie:
1. Stwórzmy tabele Menu o strukturze:
Nazwa Pola |
Typ Danych |
Opis |
---|---|---|
ID |
Autonumerowanie |
Klucz podstawowy |
rodzic |
Liczba |
Identyfikator menu nadrzędnego, dla głównego poziomu wartość ustalamy na 0 |
nazwa |
tekst |
Nazwa wyświetlana w menu |
akcja |
Tekst |
Akcja jaka ma się wykonać po kliknięciu |
parametry |
Tekst |
Parametry do wykonania akcji |
2. Wypełnijmy tabele danymi:
ID | rodzic | nazwa | akcja | parametry |
---|---|---|---|---|
1 | 0 | menu1 | ||
2 | 1 | menu1 opcja1 | openForm | UkryjOdkryj_Paski |
3 | 1 | menu1 opcja2 | openForm | Panel przełączania |
4 | 0 | menu2 | ||
5 | 4 | menu2 opcja2 | openTable | Menu |
6 | 4 | menu2 opcja2 | msg | Treść komunikatu |
Mając tak przygotowane dane możemy przystąpić do dalszej pracy.
Dynamiczne generowanie menu
W tym miejscu rozbuduje poprzedni przykład o pobranie danych z tabeli i wygenerowanie struktury, celowo pomijam funkcje już wykorzystane:
Public Sub CreateMenu() Dim cmdNewMenu As CommandBar Dim strMenuName As String Dim rootMenu As CommandBarControl Dim sql As String Dim rMenu As DAO.Recordset 'usun menu jeśli istnieje strMenuName = "MenuAplikacji" If fIsCreated(strMenuName) Then Application.CommandBars(strMenuName).Delete End If 'stwórz nowe menu Set cmdNewMenu = Application.CommandBars.Add(strMenuName, msoBarTop, True, False) With cmdNewMenu .Protection = msoBarNoProtection .Visible = True End With 'pobierz dane do poziomu 1 sql = "select id,nazwa from menu where rodzic = 0" Set rMenu = CurrentDb.OpenRecordset(sql) rMenu.MoveFirst Do Until rMenu.EOF Set rootMenu = cmdNewMenu.Controls.Add(msoControlPopup) rootMenu.Caption = rMenu!nazwa 'dodaj podmenu CreateSubMenu rMenu!id, rootMenu rMenu.MoveNext Loop rMenu.Close Set rMenu = Nothing Set rootMenu = Nothing DodajMenuOkno cmdNewMenu Set cmdNewMenu = Nothing End Sub Public Sub CreateSubMenu(rodzic As Long, ByRef m As CommandBarControl) Dim subMenu As CommandBarControl Dim sql As String Dim rSubMenu As DAO.Recordset 'pobierz dane dzieci sql = "select id,rodzic,nazwa from menu where rodzic = " & rodzic Set rSubMenu = CurrentDb.OpenRecordset(sql) rSubMenu.MoveFirst Do Until rSubMenu.EOF Set subMenu = m.Controls.Add(msoControlButton) With subMenu .Caption = rSubMenu!nazwa .OnAction = "=MnuClick(""" & rSubMenu!id & """)" End With rSubMenu.MoveNext Loop rSubMenu.Close Set rSubMenu = Nothing Set subMenu = Nothing End Sub
Zasada działania jest następująca:
1. Uruchamiam procedurę CreateMenu
2. Usuwam istniejące menu
3. Tworzę na nowo
4. Pobieram dane najwyższego poziomu (rodzic = 0)
5. Tworzę kolejne pozycje
6. Dla każdej pozycji menu wywołuje funkcje CreateSubMenu, która generuje podmenu
W efekcie otrzymam w pełni funkcjonalne menu
Dodatkowe funkcjonalności
W linijce 35 wywołuje funkcje DodajMenuOkno, zadaniem tej funkcji jest przekopiowanie systemowego menu okno, tak aby dać użytkownikowi możliwość sprawnego nawigowania pomiędzy otwartymi formularzami:
Public Sub DodajMenuOkno(ByRef cb As CommandBar) Dim iMB As Integer Dim iGW As Integer Dim cmenubar As CommandBar Dim cwindow As CommandBarControl iMB = -1 iGW = -1 For Each cmenubar In Application.CommandBars If cmenubar.Name = "Menu Bar" Then iMB = cmenubar.Index Exit For End If Next If iMB <> -1 Then For Each cwindow In Application.CommandBars(iMB).Controls If cwindow.OLEMenuGroup = msoOLEMenuGroupWindow Then iGW = cwindow.Index Exit For End If Next End If If iGW <> -1 Then Application.CommandBars(iMB).Controls(iGW).Copy cb End Sub
Działanie:
1. Szukam indeksu dla menu “menu bar”
2. Szukam na nim indeksu menu “okno”
3. Kopiuje do utworzonego menu
Obsługa kliknięć
Jak widać funkcja generująca podmenu (CreateSubMenu) dodaje do zdarzenia odwołanie do funkcji MnuClick.
To główna funkcja odpowiedzialna za całość działania nawigacji.
Jak wynika z danych w tabeli menu możemy rozróżnić 3 akcje:
1.openform – otwarcie formularza
2.openTable – otwarcie tabeli
3.msg – wyświetlenie komunikatu
Dane niezbędne do wykonania tych czynności są w kolumnie parametry i tak np. dla menu o id 3 otworzy się formularz: Panel przełączania
Obsługa w kodzie VBA:
Public Function MnuClick(ByVal id As Long) Dim sql As String Dim rAkcja As DAO.Recordset 'pobierz dane o akcji menu sql = "select akcja,parametry from menu where id=" & id Set rAkcja = CurrentDb.OpenRecordset(sql) rAkcja.MoveFirst Select Case rAkcja!akcja Case "openForm" DoCmd.OpenForm rAkcja!parametry Case "openTable" DoCmd.OpenTable rAkcja!parametry, acViewNormal Case "msg" MsgBox rAkcja!parametry End Select rAkcja.Close Set rAkcja = Nothing End Function
Działanie to nic innego jak pobranie danych z tabeli menu i wykonanie zdefiniowanej akcji.
Podsumowanie
Na tym zakończę opis pisania nawigacji w Acc2003, myślę, że to każdemu da pogląd jak to można rozwinąć i wykorzystać. Moim zdaniem najważniejsze zalety to:
1. Jedna funkcja generująca menu
2. Konfiguracja na poziomie tabeli
3. Jedna funkcja odpowiedzialna za działanie nawigacji
4. Ułatwiona nawigacja pomiędzy otwartymi formularzami (menu Okno)
Dla zainteresowanych link do przykładowej bazy.
Uwaga! Aby kod zadziałal musi być dodana referncja do Microsoft Office 11 Library
3 Comments.