get categorybuttons items caption under mouse in delphi - delphi

how can I get caption of an item or a category when mouse is entering on them?
how can I get the current caption of an item or a category when right clicking on them?
I assigned a popup menu to categorybuttons. Now I need to obtain the current item or category captions and save them in variable. Because my popup menu has an item that by clicking on it it opens a new form so I want to use this variables values here.
Something like this works at click event :
Current_Items, Current_Category: String
procedure TForm1.CategoryButtons1Click(Sender: TObject);
begin
Current_Items := CategoryButtons1.CurrentCategory.Items
[CategoryButtons1.SelectedItem.Index].Caption;
Current_Category := CategoryButtons1.CurrentCategory.Caption;
end;
But I need to obtain them when right click.
Can someone helps me to do this?
Thank you...

Edit:
Use the OnHotButton event to prepare the Current_Item variable. That gives you the Item on which the mouse right button is clicked, but not the category.
Just note however that this does not select (activate) that particular button.
var
Current_Items, Current_Category: String;
procedure TForm17.CategoryButtons1HotButton(Sender: TObject;
const Button: TButtonItem);
begin
if Button <> nil then
Current_Items := Button.Caption;
end;
Then use Current_Items to identify which button is hot when you popup the menu.

Related

TEdit with clear button [duplicate]

When use TEdit control on the right side stay small icon 'x'. How after click on icon clear TEdit box.
Tnx all!
Delphi provide TClearEditButton to clear the TEdit content. It can be added by right clicking and selecting AddItem - TClearEditButton from the popup menu. It also has a Click procedure overriden in FMX.Edit unit like:
procedure TClearEditButton.Click;
var
EditTmp: TCustomEdit;
begin
inherited Click;
EditTmp := GetEdit;
if EditTmp <> nil then
begin
if EditTmp.Observers.IsObserving(TObserverMapping.EditLinkID) then
if not TLinkObservers.EditLinkEdit(EditTmp.Observers) then
Exit; // Can't change
EditTmp.Text := string.Empty;
if EditTmp.Observers.IsObserving(TObserverMapping.EditLinkID) then
TLinkObservers.EditLinkModified(EditTmp.Observers);
if EditTmp.Observers.IsObserving(TObserverMapping.ControlValueID) then
TLinkObservers.ControlValueModified(EditTmp.Observers);
end;
end;
Which make you don't need to write OnClick event handler for the TClearEditButton unless you want to do some other job along side with clearing the edit.
If you are using a TEditButton then you should write the OnClick event handler like:
procedure TForm1.EditButton1Click(Sender: TObject);
begin
Edit1.Text:= EmptyStr;
end;

1 popup menu and 2 memo's, which memo is the menu invoked from

I have 2 memo's on a form and 1 Tpopupmenu I have assigned the popup menu as the popup menu for both memos. The pop up menu has a couple of menuitem assigned to it, when I right mouse click on either of the memo's and click on one of the menu items on its onclick event I would like to be able to know which memo is the one where the menu was invoked from but cannot figure out how to find out which memo it was!!
Could anyone give me a pointer on how to detect the underlying memo.
thanks
colin
You can use the PopupComponent property of the popup menu:
procedure TForm1.PopupItemClick(Sender: TObject);
begin
if PopupMenu1.PopupComponent = Memo1 then
..
else
..

How to detect popup of a sub-menu of a popup menu (and how to populate it dynamically)?

I have a popup menu which contains several menu items and one of them can have child items. This entry has a little arrow on the right and when you hover your mouse over it, a sub-menu will open (without clicking). Now I want to populate this sub-menu at runtime, but only if the user actually opens it. If the user never opens the sub-menu, it will be empty (maybe contain a placeholder). How could I accomplish this? Is it even possible to modify a popup-menu when it is already visible?
Thanks for your help!
There is no difference between submenus in standard menus or context (popup) menus: If a menu item has a submenu attached, then its OnClick event will fire just before the submenu is shown (note that you don't need to click for it to show up), and in that event handler you can modify the submenu (either set properties of existing items, or add new items / delete existing items).
Some demo code about dynamically adding and removing items:
procedure TForm1.FormCreate(Sender: TObject);
var
Popup: TPopupMenu;
Item, SubItem: TMenuItem;
begin
Popup := TPopupMenu.Create(Self);
PopupMenu := Popup;
Item := TMenuItem.Create(Popup);
Item.Caption := 'Test submenu';
Item.OnClick := PopupClick;
Popup.Items.Add(Item);
SubItem := TMenuItem.Create(Item);
SubItem.Caption := 'dummy';
Item.Add(SubItem);
end;
procedure TForm1.PopupClick(Sender: TObject);
var
SubmenuItem, Item: TMenuItem;
begin
SubmenuItem := Sender as TMenuItem;
// delete old items (leave at least one to keep the submenu)
while SubmenuItem.Count > 1 do
SubmenuItem.Items[SubmenuItem.Count - 1].Free;
// create new items
while SubmenuItem.Count < 3 do begin
Item := TMenuItem.Create(SubmenuItem);
Item.Caption := Format('new item created %d', [GetTickCount]);
SubmenuItem.Add(Item);
end;
end;

What is the component a popup menu click originated from

Having a popup menu attached to several components on a form (buttons, but also things like TCharts), I would like to know which component was right clicked to start the popup menu in the first place.
The Sender parameter of the click method just points to the TMenuItem, its parent to the popup menu (or the parenting menu item).
How do I get the originating component?
Did you mean PopupMenu1.PopupComponent ?
You can get the caller component within the click event of the TMenuItem of a PopupMenu by
Caller := ((Sender as TMenuItem).GetParentMenu as TPopupMenu).PopupComponent;
An Example of a PopupMenu which is assigned to several list boxes and solves the export to file functionality:
procedure TForm1.mniExportFileClick(Sender: TObject);
var Caller: TObject;
begin
if SaveTextFileDialog1.Execute then
begin
Caller := ((Sender as TMenuItem).GetParentMenu as TPopupMenu).PopupComponent;
(Caller as TListBox).Items.
SaveToFile(SaveTextFileDialog1.FileName,
StandardEncodingFromName(
SaveTextFileDialog1.Encodings[SaveTextFileDialog1.EncodingIndex]));
end;
end;
As a last resort you can use Mouse.CursorPos in TPopupMenu.OnPopup to find this component on a form. But there is probably a better/easier way.
PopUpMenu.PopupComponent indicates the component that last displayed the popup menu in response to the right mouse click
I have a bunch of panels and I want to let the user right click any of those panels and perform a "delete file" action.
So, I have a single pop-up menu associated with all those panels.
This is how I find out which panel was right clicked:
(Note: I put lots of comments to clearly explain how it works. But if you don't like it, you can compactify the code to 2 lines (see the second procedure)).
So, if you have actions assigned to that pop-up menu:
procedure Tfrm.actDelExecute(Sender: TObject);
VAR
PopMenu: TPopupMenu;
MenuItem: TMenuItem;
PopupComponent: TComponent;
begin
{ Find the menuitem associated to this action }
MenuItem:= TAction(Sender).ActionComponent as TMenuItem; { This will crash and burn if we call this from a pop-up menu, not from an action! But we always use actions, so.... }
{ Was this action called by keyboard shortcut? Note: in theory there should be no keyboard shortcuts for this action if the action can be applyed to multiple panels. We can call this action ONLY by selecting (right click) a panel! }
if MenuItem = NIL then
begin
MsgError('This action should not be called by keyboard shortcuts!');
EXIT;
end;
{ Find to which pop-up menu this menuitem belongs to }
PopMenu:= (MenuItem.GetParentMenu as TPopupMenu);
{ Find on which component the user right clicks }
PopupComponent := PopMenu.PopupComponent;
{ Finally, access that component }
(PopupComponent as TMonFrame).Delete(FALSE);
end;
If you only have a simple pop-up menu (no actions assigned):
procedure Tfrm.actDelHddExecute(Sender: TObject);
VAR PopupComponent: TComponent;
begin
PopupComponent := ((Sender as TMenuItem).GetParentMenu as TPopupMenu).PopupComponent;
(PopupComponent as TMonFrame).Delete(TRUE);
end;
You can put all that code in a single function that returns a TPanel and call it like this:
procedure Tfrm.actDelWallExecute(Sender: TObject);
begin
if GetPanelFromPopUp(Sender) <> NIL
then GetPanelFromPopUp(Sender).Delete(FALSE);
end;

TListBox Drag and Drop problems with MultiSelect enabled

I have a TListBox with multiselect and ExtendedSelect both set to true. I need to be able to drag multiple items in the list box to re-arrange them. My problem is what happens when the user clicks on an item that is already selected without holding down the CTRL or SHIFT key.
Case 1: DragMode is set to dmManual
The selection is cleared before the mouse down. This will not allow multiple items to be dragged.
Case 2: DragMode is set to dmAutomatic
The MouseDown event never fires. The selection is not cleared so dragging is OK, but the user cannot clear the selection by clicking on one of the selected items. This really causes a problem if all the items are selected or the next item the user wants to select was part of the current selection.
Note that this problem only happens if you assign something to the DragObject in the OnStartDrag procedure. I think the problem would go away if OnStartDrag would only start after the user moves the mouse. I have Mouse.DragImmediate := false set but I still get the StartDrag fired as soon as I click on an item in the list box.
I am using Delphi 7 for this project but I see the same behavior in Delphi 2007.
I have played with this for a while. And observe the same effects.
I would use Case2 and add a (Select All/Deselect All) button to the list. It even adds extra functionality and solves the most annoying part of the problem.
Use Case 2 and when the TListBox.OnMouseUp event fires check to see if multiple items are selected and were dragged. If multiple items are selected, but weren't dragged, then deselect all items apart from the clicked item.
I would use this method because Windows Explorer works this way.
Bit of a kludge but this works. DragMode on the ListBox is set to dmAutomatic.
procedure TForm1.ListBox1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
iDropIdx, i: Integer;
pDropPoint: TPoint;
slSelected: TStrings;
begin
{Which item is being dropped onto?}
pDropPoint := Point(X, Y);
iDropIdx := ListBox1.ItemAtPos(pDropPoint, False);
slSelected := TStringList.Create;
try
{Copy the selected items to another string list}
for i := 0 to Pred(ListBox1.Items.Count) do
begin
if (ListBox1.Selected[i]) then
slSelected.Append(ListBox1.Items[i]);
end;
{Find the selected items in the listbox and swap them with the drop target}
for i := 0 to Pred(slSelected.Count) do
begin
ListBox1.Items.Exchange(ListBox1.Items.IndexOf(slSelected[i]), iDropIdx);
inc(iDropIdx);
end;
finally
slSelected.Free;
end;
end;
I'm not sure why this makes a difference but if I change the DragObject to be a TDragControlObjectEx (instead of a TDragObjectEx) I get the behavior I am looking for. Drag mode is set to Automatic.
I tried to look and see what this was affecting but I could not figure it out.

Resources