Link to home
Start Free TrialLog in
Avatar of sara_gijs
sara_gijs

asked on

Dynamic PopupMenu Generation

Hello. I'm a beginning Delphi programmer, but I'm doing the best I can.

I'm trying to make a dynamic generated PopupMenu, with data from the windows registry. I have a tree-structure in my registry, and I want this to be extracted by my program, and put into a PopupMenu; including the subdirs. It is not sure how many levels deep the tree-structure is.

This brings 2 problems:
1> I managed to create the menuItems, but I don't know how to add a sub-item to a dynamic generated Item.

2> Making a recursive function to walk trough the registry. I know how it works in theory, but I can't get it working in delphi


I hope my question is clear.
Avatar of classmate
classmate
Flag of Norway image

1> Way of creating sub-items

procedure TForm16.FormContextPopup(Sender: TObject; MousePos: TPoint;
  var Handled: Boolean);
var
  pm : TPopupMenu;
  mi, mi1, mi2, mi11, mi21, mi22, mi221 : TMenuItem;

begin
  pm    := TPopupMenu.create(nil);
  try
    mi    := pm.items;

    mi1   := TMenuItem.Create(mi); // you also should add appropriate .caption properties...
    mi11  := TMenuItem.Create(mi1);

    mi2   := TMenuItem.Create(mi);
    mi21  := TMenuItem.Create(mi2);
    mi22  := TMenuItem.Create(mi2);
    mi221 := TMenuItem.Create(mi22);

    mi.Add   ([mi1, mi2]);
    mi1.Add  (mi11);
    mi2.Add  ([mi21, mi22]);
    mi22.Add (mi221);


    windows.clienttoscreen (handle, MousePos);
    with MousePos do
      pm.Popup(x,y);
  except
    // implement as needed
  end;
  pm.free;
  handled := true;
end;


i'll come back with a solution for 2>

classmate.
by the way, some registry keys are so full of subkeys that there won't be space for all the menu items on the screen.

Furthermore, since registry is huge, you might want to fill submenus with items as the owner item is clicked, instead of initializing the whole menu at once. That is my advice unless you have a good reason for the recursion approach... (such as learning about recursion in delphi)


regards
classmate.

Avatar of sara_gijs
sara_gijs

ASKER

Okay; I managed to come that far too. But how do I add a subitem to an item if I don't know the name of the Item?

For example I have this treestructure:

+ car
|      |
|      + opel
|      + fort
|
+bike
     |
     + fast bike
     + slow bike


I already created a Menupopup with an Item 'Sessions1' in it. I Use this code to generate the list:

procedure TFormConf.MakeMenu();
var
  Reg: TRegistry;
  DirList: TStrings;
  Teller: integer;
  Item: TMenuItem;
  Hostname: String;

begin
  Reg := TRegistry.Create;
  Reg.OpenKey('\\Software\\SARA\\SARAwrap\\Sessions', False);

  DirList := TStringList.Create;
  Reg.GetKeyNames(DirList);

  Sessions1.Clear;

  for Teller := 0 to Dirlist.Count -1 do
  begin
    Hostname := DirList[teller];
    Item := TMenuItem.Create(FormConf);
    Item.Caption := Hostname;
    Item.OnClick := FakeMenuClick;
    Sessions1.Add(Item);
  end;
end;


But How do I at an subitem to 'cars', if I don't know the name (this is different every time)
ASKER CERTIFIED SOLUTION
Avatar of Evarest
Evarest

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Oh yeah,
the line

 Memo1.Lines :=DirList;

was for debugging only. you can delete it :)

Evarest
Here is my recursion routine. It's like you've done it, with a slight modification...

procedure TForm16.FormContextPopup(Sender: TObject; MousePos: TPoint;
  var Handled: Boolean);


procedure fillmenu (OwnerItem : TMenuItem; Reg : TRegistry; Key : String);
var
  Teller: integer;
  DirList: TStrings;
  Hostname: String;
  Item : TMenuItem;
begin
  Reg.OpenKey(Key, False);

  DirList := TStringList.Create;
  Reg.GetKeyNames(DirList);

  for Teller := 0 to Dirlist.Count -1 do
  begin
    Hostname := DirList[teller];
    Item := TMenuItem.Create(OwnerItem);
    Item.Caption := Hostname;
//    Item.OnClick := FakeMenuClick;nb
    OwnerItem.Add(Item);
    FillMenu (Item, Reg, Key + '\' + Hostname);
  end;

  DirList.Free;
end;

var
  pm : TPopupMenu;
  Reg: TRegistry;

begin
  Reg := TRegistry.Create;
  Reg.RootKey := HKEY_LOCAL_MACHINE;

  pm := TPopupMenu.create(nil);
  FillMenu (pm.Items, Reg, '\Software\borland');

  windows.clienttoscreen (handle, MousePos);
  with mousepos do
    pm.Popup(x, y);

  pm.free;
  reg.free;
  handled := true;
end;

For the example i used the local key to borland software, so that the example should be working at any location with delphi installed.

regards
classmate
Evarest, your solution might work but it is many lines too long ;-)
Hi, sara_gijs :-)

Why did not I get the points ?? As far as I can see, my solution is the best one.
Well; my excuses for that. Evarest gave me the first good working example.

I had to give someone the points so I gave it to him.  Is there a possebility that I can give you points too?


This is my first question here, so it is all new to me.



But now I'm out of point. Maybe I should go help some people with unix/linux-networking problems :)
You are right. Your code is better.

You modified my source to my needs, and it works. And it is smaller.

Still Evarest did a good job too.


Don't know what to do now.... :)
hehe, no big deal.
You seem to be scandinavian, as i too am (why else should a loop variable be called "teller").
You are hereby excused =)

-Jeg trenger vel neppe poengene, men er ganske pirkete på programmeringsteknikk.
Så jeg syntes det var litt småkjipt at en annen stakk av med respekten jeg skulle ha hatt...
Men nå har du sagt unnskyld, så da skal jeg ikke være sur lenger =)

classmate
no dutch :P


Ik snap dus geen hol van wat je zei
Ey uhh but I have one little problem left.

I added 'item.onclick := fakemenuclick' to the loop, but now ALL the Items get that....


So the menu is right, only when I click a menu to see the submenu's; Fakemenuclick begins to do it work.


How do I escape from this?

It depends on what the event handler is supposed to do...

if you are in a infinite loop, press ctrl + F2 in delphi. This should halt your application.
Ik snap er ook niks van van wat classmate zei :) Maar over de code: snel geschreven en diende nog heel wat opgemaakt te worden. Het leek me het best dat je dat zelf probeerde daarom mijn "If you want something else explained about this code, let me know!". Ik heb Delphi ook door voorbeelden geleerd, en geloof me daarvan leer je het meest.

Translation:
About my code: quickly written and in need of improvement. However i thought this was an interesting exercise for the sara_gijs.

Anyway, thanx for the points ;)
Evarest