tags:

views:

1871

answers:

3

I am using a popup menu in Delphi. I want to use it in a "radio group" fashion where if the user selects an item it is checked and the other items are not checked. I tried using the AutoCheck property, but this allows multiple items to be checked. Is there a way to set the popup menu so that only one item can be checked?

+1  A: 

Zartog is right, but if you want to keep the checkbox, assign this event to every item in the popup menu.

Note that this code is a little hairy looking because it does not depend on knowing the name of your popup menu (hence, looking it up with "GetParentComponent").

procedure TForm2.OnPopupItemClick(Sender: TObject);
var
  i : integer;
begin
  with (Sender as TMenuItem) do begin
    //if they just checked something...
    if Checked then begin
      //go through the list and *un* check everything *else*
      for i := 0 to (GetParentComponent as TPopupMenu).Items.Count - 1 do begin
        if i <> MenuIndex then begin  //don't uncheck the one they just clicked!
          (GetParentComponent as TPopupMenu).Items[i].Checked := False;
        end;  //if not the one they just clicked
      end;  //for each item in the popup
    end;  //if we checked something
  end;  //with
end;

You can assign the event at runtime to every popup box on your form like this (if you want to do that):

procedure TForm2.FormCreate(Sender: TObject);
var
  i,j: integer;
begin
  inherited;

  //look for any popup menus, and assign our custom checkbox handler to them
  if Sender is TForm then begin
    with (Sender as TForm) do begin
      for i := 0 to ComponentCount - 1 do begin
        if (Components[i] is TPopupMenu) then begin
          for j := 0 to (Components[i] as TPopupMenu).Items.Count - 1 do begin
            (Components[i] as TPopupMenu).Items[j].OnClick := OnPopupItemClick;
          end;  //for every item in the popup list we found
        end;  //if we found a popup list
      end;  //for every component on the form
    end;  //with the form
  end;  //if we are looking at a form
end;

In response to a comment below this answer: If you want to require at least one item to be checked, then use this instead of the first code block. You may want to set a default checked item in the oncreate event.

procedure TForm2.OnPopupItemClick(Sender: TObject);
var
  i : integer;
begin
  with (Sender as TMenuItem) do begin
    //go through the list and make sure *only* the clicked item is checked
    for i := 0 to (GetParentComponent as TPopupMenu).Items.Count - 1 do begin
      (GetParentComponent as TPopupMenu).Items[i].Checked := (i = MenuIndex);
    end;  //for each item in the popup
  end;  //with
end;
JosephStyons
He should also add the code that checks that at least one menu item is checked and that adds the check back user unchecks the checked entry.That should be simple given your examples.
gabr
I'm not sure that is his goal, but I added a block to handle that in the answer. It actually simplifies things a little.
JosephStyons
This is definitely not the way to go: this functionality is already built-in. See Zartog's and Gerry's posts, and combine the two.
onnodb
+7  A: 

To treat the popup (or any other) menu items like radio group items, set the 'RadioItem' property to true for each item you want to have in the radio group.

Instead of showing a checkmark, it will show a bullet by the selected item, but it will work the way you want, and the visual cue will actually match a windows standard.

Zartog
+1  A: 

To enlarge on Zartog's post: Popup menus in Delphi (from at least D6) have a GroupIndex property which allow you to have multiple sets of radio items within a menu. Set GroupIndex to 1 for the first group, 2 for a second etc.

So: Set AutoCheck = True Set RadioItem = True Set GroupIndex if you need more than one group of radio items

Gerry