How to repaint a Tpopmenu in Delphi? - delphi

I need to change the text of a TMenuItem in Delphi 7, when the popup menu is already popped up.
My popup menu has
OwnerDraw := true;
I'd like to use:
popupmenu.repaint();
or
popupmenu.refresh();
but they do not exist. How can I do it?

You can call MenuChanged on the menu item to force it to be updated. This is a protected member to you need to gain access to that member by the well-known protected member hack.
type
THackedMenuItem = class(TMenuItem);
....
THackedMenuItem(MyMenuItem).MenuChanged(True);//forces redraw of owner drawn item

Related

How to let Parent component get click events of child components?

I have a FireMonkey application with multiple buttons on it (actually, rectangles). I want to have one procedure called on any click on the Form, besides the specific action of each button.
Since the HitTest of each child component is set to True, the parent's HitTest is automatically false.
So what is the right way to deal with this?
A silly workaround would be to assign this procedure to each button's OnClick event, but this will not make any sense when I have a Form with hundreds of buttons on it.
I found solution for vcl.
you can find component base of mouse position by this code:
var
ctrl : TWinControl;
begin
ctrl := FindVCLWindow(Mouse.CursorPos);
if ctrl.Name = '' then
ShowMessage(ctrl.Owner.Name);
For FireMonkey no result founded but You can get mouse position on form and analyze component base on result of that point and find name of it then proceed to your event base of that component.
A Simple Interceptor/Interposer Class of TRectangle did the job!
Thanks to everyone for their input.

How to dynamically scroll in Tlistbox Delphi xe5

TListbox.topIndex is not apparent in Delphi xe5. How do I perform a similar function ? I would like to have the listbox scroll so that the selected item is at the top of the listbox.
I have found other examples where I can set ListBox.itemIndex, but that doesn't scroll so that the selected item is at the top of the listbox.
Thank you in advance.
I have used this code which works:
var
THackListBox = type TListBox;
begin
THackListBox(ListBox1).VScrollBar.Value := 0;
The VScrollBar property is protected but this method exposes the property and allows the value to be set to zero.
On Windows, the VCL TListBox has a public TopIndex property, which internally uses the LB_SETTOPINDEX message.
There is no equivalent in the FireMonkey TListBox. The only option I see would be to call the ListBox's ScrollTo() method to manually scroll the ListBox so the target list item appears where you want it to be.

Is possible for a menu item to receive an OnClick event even when it's not enabled?

I'm trying to enable an Administrator to enable/disable menu items in the main menu of my Application by Ctrl+Clicking them. To do that I've injected the TMenuItem class in my main form with a custom version and overridden the Click virtual method, like so:
uses
Forms, Menus;
type
TMenuItem = class(Menus.TMenuItem)
public
ControlActivationState: Boolean;
procedure Click; override;
end;
TMyMainForm = class(TForm)
...
procedure TMenuItem.Click;
begin
if ControlActivationState and IsKeyPressed(VK_CONTROL) then
Self.Enabled := not Self.Enabled
else
inherited;
end;
It works, but only for the top level menu.
Why the top level menu items receives OnClick events even when they are disabled and the other menu items don't?
Is there a way to make the child menu items receive those events too?
The top level OnClick event is triggered by receipt of a WM_INITMENUPOPUP message. That message is sent even when the top level item is disabled. I'm not sure why it is sent in that scenario, but it is. And the same is true for a sub-item that has children.
However, for a sub-item without children, the OnClick is triggered by a WM_COMMAND message. But the system never even sends the message if the menu item is disabled.
What you are attempting to do cannot be readily done. The only way I can see you doing it is to handle the raw mouse and keyboard events. Personally, I would not contemplate doing so.
TMenuItem is a TComponent, i.e. it's not a windowed control and it doesn't have classical events. Instead, click events which happen on a real windowed control are delegated to a TMenuItem instance. I don't know which window control is the real host for events but even if I did I think it would be hard to determine which TMenuItem corresponds to the actual click point.
My advice is to make a dedicated window for menu editing with a tree control which generically populates its items at runtime based on the actual menu layout, and then provide enable/disable for the tree nodes which reflect on the corresponding menu items. You can then save/load menuitem list, etc. This should be much cleaner and easier then diving into the murky depths of VCL and figuring out (and overriding) how events are propagated from 'real' controls to design-time representations called TComponents...
In fact, you are trying to do it the hard way...
The easy solution to your problem would be to override the OnDrawItem() method of your TMenuItem to display it like it was disabled, and handle the OnClick event alternatively.
(Do not forget to set the .OwnerDraw property of the menu to make this solution work.)
Edit:
According to the Delphi help using the OnAdvancedDrawItem event makes it more easy because it provides intormation about the menuitem itself.

How to avoid the "Open IME" popup in a StringGrid?

In a StringGrid, sometimes I get the unwanted menu below when I right-click. Is this a Windows popup?
How to I prevent this popup from appearing rather than my own?
I have goAlwaysShowEditor in my Options.
I have set StringGrid.PopupMenu to my popup.
I've set StringGrid.OnMouseDown to show my popup if it's a right click.
You can override the virtual CreateEditor method like this way (not a good solution though, I know :-):
type
TStringGrid = class(Grids.TStringGrid)
protected
function CreateEditor: TInplaceEdit; override;
end;
implementation
function TStringGrid.CreateEditor: TInplaceEdit;
begin
Result := inherited CreateEditor;
TMaskEdit(Result).PopupMenu := Form1.PopupMenu1;
end;
That is the popup menu found in every Windows EDIT control. Possible the world's most known menu (the only competition comes from the system menu). You want it, because your user's expect it (and need it). When you edit the text in a cell, the TStringGrid control actually creates a standard Windows EDIT control, which is great. And thus you get its popup menu.
In addition, to show your own popup menu (when you are not editing a cell), you don't need to set the OnMouseDown handler. It is enough to set the PopupMenu property. In fact, it is very bad to use the OnMouseDown handler to trigger a popup menu, because then the menu will only be shown when the user right-clicks the control (and not, for instance, when he presses the "context" button on his keyboard).
If you really want your own popup menu to show, even when the user is editing a cell, you really have to give him his usual options for undo, copy, cut, paste, Unicode stuff, etc., manually. Surely you don't want that?

delphi 2009 accelerators

How to remove the Accelerators from TMainMenuActionBar ?
can't seem to find the AutoHotKey = maManual property to change, nor to find any other property that will cause the right effect.
(Assuming the question is about TActionMainMenuBar) you would set the AutoHotKeys property through the ActionManager component that the action bar is linked to (through its ActionManager property). Unlike the TMainMenu's AutoHotKeys, this one is a boolean property.
To set the property at design time,
Select the 'ActionManager' component on the form
Click the ... button on the right side of the ActionBars property in OI.
Select your MainMenuBar from the popped up Editing ActionManager1.ActionBars' dialog.
Click the ... button on the right side of the Items property in OI, which will launch the Editing ActionManager1.Items dialog
Do not select any of the items at this time. Instead, set the AutoHotKeys property to True or False in OI.
At run time you can do:
ActionManager1.ActionBars[0].Items.AutoHotKeys := False;
Note that you might need to re-set the Caption of an Item after toggling AutoHotKeys. I.e. 'F&ormat' -> 'Format'.

Resources