Alweer geen excel

Menu's en event handling

Arnout van Kempen schrijft in deze rubriek over pret maken met computers. Hij gaat aan de slag met Pascal.

We hebben twee procedures die de ruggengraat vormen van onze applicatie: InitMenuBar bouwt het menu op, HandleEvent verwerkt de events die uit dat menu voortkomen. Tijd om ze in te vullen. InitMenuBar zorgt ervoor dat er een menubalk bovenaan het scherm verschijnt met onze opties. HandleEvent luistert naar wat de gebruiker kiest en roept de bijbehorende actie aan. Samen vormen ze de brug tussen interface en functionaliteit.

InitMenuBar: het menu bouwen

Procedure TSysInfoApp.InitMenuBar;
Var
  R: TRect;
Begin
  GetExtent(R);
  R.B.Y := R.A.Y + 1;
  MenuBar := New(PMenuBar, Init(R, NewMenu(
    NewSubMenu('~I~nfo', hcNoContext, NewMenu(
      NewItem('~C~PU', 'F2', kbF2, cmSysInfo, hcNoContext,
      NewLine(
      NewItem('E~x~it', 'Alt-X', kbAltX, cmQuit, hcNoContext,
      Nil)))),
    Nil)
  )));
End;

Deze procedure wordt automatisch aangeroepen door   TApplication.InitHet Virtual keyword in de declaratie zorgt ervoor dat onze versie wordt gebruikt in plaats van de lege default van TApplication.

TRect en schermcoördinaten

GetExtent(R)vult de variabele R met de afmetingen van het hele scherm. TRect is een record met twee punten: A (linkerbovenhoek) en B (rechteronderhoek). Elk punt heeft een X en Y coördinaat.

Als het scherm bijvoorbeeld 80 kolommen breed en 25 regels hoog is, krijg je: R.A.X = 0, R.A.Y = 0, R.B.X = 80, R.B.Y = 25.

De regel R.B.Y := R.A.Y + 1 maakt de rechthoek maar één regel hoog. We nemen de volledige breedte, maar alleen de eerste regel. Dat is waar de menubalk komt.

Het menu construeren

De rest is een geneste structuur van function calls. Het lijkt ingewikkeld, maar het is systematisch opgebouwd. Van binnen naar buiten:

NewItem maakt een menu-item. De parameters:

  • '~C~PU': de tekst, met tildes (~) rondom de letter die je als sneltoets kunt gebruiken (Alt-C)
  • 'F2': de tekst die rechts verschijnt om de shortcut aan te geven
  • kbF2: de werkelijke toetscode die dit item triggert
  • cmSysInfo: het commando dat verstuurd wordt als je dit item kiest
  • hcNoContext: help context (voor F1-help, hier niet gebruikt)
  • Het laatste parameter is een pointer naar het volgende item in de lijst (of Nil)

NewLine voegt een scheidingslijn toe in het menu.

NewMenu groepeert items samen tot een lijst. NewSubMenu maakt een hoofdmenu-item met een dropdown. De eerste parameter ('~I~nfo') is wat je in de menubalk ziet, de tweede is de help context, de derde is het submenu dat openklapt als je erop klikt.

De hele constructie werkt van binnen naar buiten. Je bouwt eerst de individuele items (CPU, Exit), dan groepeer je ze in een menu, dan stop je dat menu in een submenu (Info) en dat wordt dan de inhoud van de menubalk.

Het laatste Nil sluit de lijst af. Als je meer hoofdmenu-items wilt (bijvoorbeeld File, Edit, Info), zou je daar nog meer NewSubMenu calls toevoegen voordat je Nil zet.

HandleEvent: events afhandelen

Procedure TSysInfoApp.HandleEvent(Var Event: TEvent);
Begin
  TApplication.HandleEvent(Event);
  If Event.What = evCommand Then
  Begin
    Case Event.Command Of
      cmSysInfo: ShowSysInfo;
    Else
      Exit;
    End;
    ClearEvent(Event);
  End;
End;

Deze procedure wordt aangeroepen voor elk event dat binnenkomt. De  Event parameter bevat alle informatie: wat voor soort event het is, welke toets, welk commando etc.

De parent eerst

TApplication.HandleEvent(Event)roept de oorspronkelijke HandleEvent aan van TApplication. Die verwerkt standaardzaken zoals Alt-X voor afsluiten, F10 voor het activeren van het menu, en andere basisfunctionaliteit. Door die eerst aan te roepen, zorg je dat die functionaliteit blijft werken. Pas daarna kijken we naar onze eigen commando's.

Command check

If Event.What = evCommand filtert alleen command events. Niet elke toetsaanslag is een commando, soms is het gewoon een letter die je typt in een tekstveld. Alleen als het een echt commando is (van een menu, een button, een shortcut), gaan we verder.

De case statement kijkt welk commando het is. Als Event.Command gelijk is aan cmSysInfo, roepen we ShowSysInfo aan. Voor andere commando's (de Else tak) doen we niets en verlaten we de procedure.

ClearEvent

Na het afhandelen van het commando roepen we ClearEvent(Event)aan. Dat zet het event op "verwerkt". Zonder die call zou het event verder gaan naar andere objecten die misschien ook willen reageren. Door het te clearen zeg je: "ik heb dit afgehandeld, niemand anders hoeft er nog naar te kijken".

Dit voorkomt dat één toetsaanslag meerdere acties triggert. Als jij cmSysInfo al hebt verwerkt, hoeft niemand anders er meer mee aan de slag.

Uitbreiden

Als je later meer functies toevoegt,  bijvoorbeeld informatie over geheugen of schijven, voeg je gewoon nieuwe items toe aan InitMenuBar en nieuwe cases aan HandleEvent. De structuur blijft hetzelfde. Elke nieuwe functie is een nieuw menu-item met een nieuw commando en een nieuwe case die de bijbehorende ShowXxx procedure aanroept.

Arnout van Kempen is naast computernerd ook directeur compliance & risk bij aaff. Hij schrijft op persoonlijke titel.

Gerelateerd

reacties

Reageer op dit artikel

Spelregels debat

    Aanmelden nieuwsbrief

    Ontvang elke werkdag (maandag t/m vrijdag) de laatste nieuwsberichten, opinies en artikelen in uw mailbox.

    Bent u NBA-lid? Dan kunt u zich ook aanmelden via uw ledenprofiel op MijnNBA.nl.