VCL Delphi

Title: Selecting an Item in a TListBox via Right-Click.
Question: At times, Ive needed to make a ListBoxs PopUp menu display information specific to the Item selected passed via ItemIndex. Right-Clicking on an Item however, doesnt change the ListBoxs ItemIndex as Left-Clicking does. This shows you, by help of an example, how this can be achieved.
Answer:
Say you have a ListBox filled with, oh lets call them Widgets.
type TWidget = class(Tobject)
WidgetName : string;
WidgetStatus : boolean;
End;
Widgets : array [0..10] of TWidget
Each WidgetName is displayed in the ListBox.
You want to be able to change each Widgets status via a WidgetPopUp Menu which is attached to the ListBoxs OnPopUp event. The PopUp displays the Widgets status :
Active checked if active, unchecked if not. Clicking on Active toggles the status.
Problem: Left-clicking on the ListBox selects a Widget, Right-clicking (and displaying the PopUp) does not : if the mouse is over a Widget different from the selected one, the PopUp will display the status of the currently selected Widget - and not the Widget the mouse is over.
Fortunately, the ListBoxs OnMouseDown event fires before the PopUps OnPopUp so we can use the OnMouseDown event to set the ItemIndex prior to the PopUp displaying.
TlistBox has a method: ItemAtPos(Pos: TPoint; Existing: Boolean): Integer;
Which, if an Item is found at Pos, returns the Items Index. If an Item is not found, and Existing is set to True ItemAtPos returns 1, if Existing is set to False, ItemAtPos returns the Index of the last Item in the ListBox plus 1.
Using this in combination with the OnMouseDown event solves our problem:
The OnMouseDown code:
procedure TForm1.WidgetListMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
MousePos : TPoint;
OverItemIndex : integer;
begin
MousePos.x := X;
MousePos.y := Y;
if Button = mbRight then
begin
OverItemIndex := WidgetList.ItemAtPos(MousePos,False);
WidgetList.ItemIndex:=OverItemIndex;
end;
end;
The OnPopUp code:
procedure TForm1.PopupMenu1Popup(Sender: TObject);
var
Index : integer;
begin
Index := WidgetList.ItemIndex;
PopUpMenuItemActive.Checked := Widgets[Index].WidgetStatus;
end;
The OnClick code for the "Active" PopUp menu Item:
procedure TForm1.PopUpMenuItemActiveClick(Sender: TObject);
var
Index : integer;
begin
Index := WidgetList.ItemIndex;
Widgets[Index].WidgetStatus := not Widgets[Index].WidgetStatus;
PopUpMenuItemActive.Checked:=not PopUpMenuItemActive.Checked;
end;