Toon posts:

[Delphi] Dynamisch menu & Shortcuts

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik ben tegen een probleem in Delphi aangelopen. Misschien dat het een bug is in de VCL, maar het kan ook zijn dat ik iets over het hoofd heb gezien. Ik vond het toch interessant om het hier even te laten zien. Hopelijk is er iemand die weet hoe het opgelost kan worden.

Het zit zo: ik heb een form met een mainmenu. In dat menu zit een submenu dat tijdens runtime gevuld wordt met menu-items. Dat kan zelfs meerdere keren tijdens het draaien van het programma gebeuren. Dit dynamisch gemaakte menu bevat enkele items die ook met een shortcut op te roepen zijn. In mijn geval Ctrl+0 t/m Ctrl+9. Op het moment dat je op het menu klikt, of dat je de sneltoets gebruikt om het menu-item te activeren, wordt in de event-handler het menu opnieuw gevuld.

In code ziet dit er als volgt uit:
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
procedure TformTest.fillMenu;
var
  menuItem: TMenuItem;
begin
  // menu leegmaken
  menuItems.Clear;

  // nieuw item aanmaken, sneltoets instellen
  menuItem          := TMenuItem.Create(menuItems);
  menuItem.Caption  := 'Test-item';
  menuItem.ShortCut := ShortCut(Word('0'), [ssCtrl]);
  menuItem.OnClick  := ItemClick;

  // item toevoegen als submenu
  menuItems.Add(menuItem);
end;

procedure TformTest.ItemClick(Sender: TObject);
begin
  // melding geven als er geklikt is op het menu-item
  MessageBox(Handle,'Menu clicked','Test',MB_OK);
  fillMenu;
end;
Wanneer ik nu op het menu-item klik, gaat het goed. Er verschijnt een berichtje 'Menu clicked' en ik kan weer doorwerken. Maar het gaat fout als ik de sneltoets gebruik. Dan verschijnt de melding 'Menu clicked' nog wel, maar als ik deze wegklik komt hij meteen weer. Het programma komt nu in een endless loop terecht. Ik heb geen idee hoe dit komt, het zou immers niets uit mogen maken hóe je precies in de eventhandler terecht komt, of dat nu door muisklik of door sneltoets is. Maar toch gaat het juist wél goed als je klikt, en níet als je het via de sneltoets doet.

[ Voor 9% gewijzigd door Verwijderd op 06-04-2003 09:09 . Reden: code-tag als delphi ]


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 22:26

Tomatoman

Fulltime prutser

Je veroorzaakt blijkbaar een oneindige lus doordat ItemClick fillMenu aanroept. Dat kun je heel gemakkelijk ondervangen door een message aan TformTest te posten die fillMenu aanroept. Zo weet je zeker dat eerst alle event handlers worden afgewikkeld voordat fillMenu wat doet.

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const
  WM_FILLMENU = WM_USER;

type
  TformTest = class(TForm)
  private
    WMFillMenu(var Message: TMessage); message WM_FILLMENU;
    ....
  end;

...

procedure TformTest.WMFillMenu(var Message: TMessage); 
begin
  fillMenu;
end;

procedure TformTest.ItemClick(Sender: TObject);
begin
  // melding geven als er geklikt is op het menu-item
  MessageBox(Handle,'Menu clicked','Test',MB_OK);
  PostMessage(Handle, WM_FILLMENU, 0, 0);
end;

[ Voor 10% gewijzigd door Tomatoman op 06-04-2003 01:02 ]

Een goede grap mag vrienden kosten.


Verwijderd

Topicstarter
tomatoman schreef op 06 April 2003 @ 00:21:
Je veroorzaakt blijkbaar een oneindige lus doordat ItemClick fillMenu aanroept. Dat kun je heel gemakkelijk ondervangen door een message aan TformTest te posten die fillMenu aanroept. Zo weet je zeker dat eerst alle event handlers worden afgewikkeld voordat fillMenu wat doet.
Dankjewel, dit loste het probleem meteen op. Jammer dat hier geen 'mooie' oplossing voor is binnen de VCL, maar het werkt zo ook prima.