I have one TListBox with 'movie' items and another one with 'snapshots'. I want to use one popup menu for both Listboxes. However, in the onClick event for a popups menuitem, how do I resolve which list box was used?
I tried this:
void __fastcall TMainForm::DeleteAll1Click(TObject *Sender)
{
TListBox* lb = dynamic_cast<TListBox*>(Sender);
if(lb == mMoviesLB)
{
...
where DeleteAll1 is a TMenuItem in the Popup menu. The lb is always NULL so there is something missing here..
The TPopupMenu::PopupComponent property tells you which UI control displayed the popup menu, eg:
void __fastcall TMainForm::DeleteAll1Click(TObject *Sender)
{
TListBox* lb = dynamic_cast<TListBox*>(PopupMenu1->PopupComponent);
...
}
If the TPopupMenu is displayed automatically (ie: right-clicking on a control when TPopupMenu::AutoPopup is true), the PopupComponent is populated automatically. However, if you call TPopupMenu::Popup() yourself, the PopupComponent will be NULL unless you assign it beforehand, eg:
PopupMenu1->PopupComponent = ListBox1;
PopupMenu1->Popup(X, Y);
Related
When using DockPanelSuite, is it possible to have a context menu for the tab strip that is different from the one for a document tab? For example, right click an empty space on the tab strip and get one context menu then right click a document tab and get a different context menu specific to the document.
I tried setting the ContextMenuStrip property of the DockPanel. I got a context menu for any empty space on the DockPanel control as well as the document tab strip when visible and all open document tabs. That's a good start but I really only wanted the context menu for the tab strip. Not the main control or any tabs.
I also followed along with the sample project to make a context menu for the document by setting the TabPageContextMenuStrip property of the DockContent form. I discovered that you get a document specific context menu by right clicking the document tab, but it also overrides the DockPanel's ContextMenuStrip. While that is useful, it's still not the desired result.
Edit:
Updating this post in case anyone else is interested in achieving the objective of the question.
After much source code analysis and testing, I concluded that the objective could not be achieved using the available public Properties, Methods, and Events. However, we can achieve the goal by using a bit of reflection.
Discoveries:
DockContent.ContextMenuStrip
This property does nothing for the DockPanel. It will provide a context menu in the client area of the document. However, for some reason, the RichTextBox control set to Fill in the provided sample blocks the context menu from popping up.
DockContent.TabPageContextMenuStrip
This property causes the associated ContextMenuStrip to display when the document is active. However, it displays when you right click anywhere on the tab strip, not just when you right click the document tab.
Solution:
First, add a public property to the DockContent form which will contain a reference to the context menu.
public ContextMenuStrip TabContextMenu { get { return contextMenuTabPage; } }
Next, add an event handler in the MDI main form for the DockPanel.ActiveDocmentChanged event. This will be used to add an event handler to the tab strip after it’s been created.
this.dockPanel.ActiveDocumentChanged += new System.EventHandler(this.dockPanel_ActiveDocumentChanged);
private void dockPanel_ActiveDocumentChanged(object sender, EventArgs e)
{
// Hook into the document pane tabstrip mouse up event
// if we haven't already.
if (dockPanel.ActiveDocumentPane != null
&& dockPanel.ActiveDocumentPane.TabStripControl != null
&& dockPanel.ActiveDocumentPane.TabStripControl.Tag == null)
{
dockPanel.ActiveDocumentPane.TabStripControl.Tag = "MouseUp Hooked";
dockPanel.ActiveDocumentPane.TabStripControl.MouseUp +=
TabStripControl_MouseUp;
}
}
Finally, add the event handler for the TabStripControl.
private void TabStripControl_MouseUp(object sender, MouseEventArgs e)
{
// Capture right click action
if (e.Button == MouseButtons.Right)
{
ContextMenuStrip menu = contextMenuDocumentPane;
Point screenPos = Cursor.Position;
Point tabstripsPos = dockPanel.ActiveDocumentPane
.TabStripControl.PointToClient(screenPos);
// Determine if cursor is over a tab
var tabstrip = dockPanel.ActiveDocumentPane.TabStripControl;
var tabs = tabstrip.GetType()
.GetProperty("Tabs", BindingFlags.Instance |
BindingFlags.NonPublic).GetValue(tabstrip);
foreach (var tab in (IEnumerable)tabs)
{
var bounds = tab.GetType()
.GetProperty("Rectangle")
.GetValue(tab);
if (((Rectangle)bounds).Contains(tabstripsPos))
{
// Display context menu for this document tab
var document = tab.GetType()
.GetProperty("Content")
.GetValue(tab);
menu = ((ContentWindow)document).TabContextMenu;
}
}
// Show appropriate context menu
menu.Show(screenPos);
}
}
I have a TForm with two TMemo objects and one TPopupMenu. Both TMemos are using the same TPopupMenu.
The popup menu has one item for 'clearing' the Memo, through the use of a TAction.
My question is, when clicking on the Menu item on one of the TMemos, how can I figure out which TMemo was the one that displayed the TPopupMenu?
I have the following code in the TAction's execute function:
TAction* action = dynamic_cast<TAction*>(Sender);
TMenuItem* item = dynamic_cast<TMenuItem*>(action->ActionComponent);
if(item)
{
if(dynamic_cast<TMemo*>(item->Owner))
{
dynamic_cast<TMemo*>(item->Owner) -> Clear();
}
}
But the TMenuItem's owner is not a TMemo.
Any hints? I hope to avoid to have to use two different TPopupMenus.
You need to use the TPopupMenu::PopupComponent property to know which TMemo invoked the menu:
TMemo *memo = dynamic_cast<TMemo*>(PopupMenu1->PopupComponent);
if (memo)
memo->Clear();
Or, if you want to discover the TPopupMenu that the TMenuItem is linked to:
TAction* action = static_cast<TAction*>(Sender);
TMenuItem* item = dynamic_cast<TMenuItem*>(action->ActionComponent);
if (item)
{
TPopupMenu *popup = dynamic_cast<TPopupMenu*>(item->GetParentMenu());
if (popup)
{
TMemo *memo = dynamic_cast<TMemo*>(popup->PopupComponent);
if (memo)
memo->Clear();
}
}
I am using C++Builder XE4 32bit VCL platform. I am writing for Windows OS.
I have a MainForm with a lot of components on it. When I press a keyboard arrow key and the Form's OnShortCut event is triggered, how do I determine which component has the program focus?
I have different actions which must be taken based on which component has the focus.
void __fastcall TMainForm::FormShortCut(TWMKey &Msg, bool &Handled)
{
//determine which component has the focus.
}
Use the global Screen->ActiveControl property:
Indicates which control currently has input focus on the screen.
Read ActiveControl to learn which windowed control object in the active form currently receives the input from the keyboard.
void __fastcall TMainForm::FormShortCut(TWMKey &Msg, bool &Handled)
{
TWinControl *ctrl = Screen->ActiveControl;
if (ctrl == Control1)
{
// do something...
}
else if (ctrl == Control2)
{
// do something else...
}
// and so on...
}
Or, you can use the Form's own ActiveControl property:
Specifies the control that has focus on the form.
Use ActiveControl to get or set the control that has focus on the form. Only one control can have focus at a given time in an application.
If the form does not have focus, ActiveControl is the control on the form that will receive focus when the form receives focus.
void __fastcall TMainForm::FormShortCut(TWMKey &Msg, bool &Handled)
{
TWinControl *ctrl = this->ActiveControl;
if (ctrl == Control1)
{
// do something...
}
else if (ctrl == Control2)
{
// do something else...
}
// and so on...
}
My application is using two forms. When I click a panel in main form, the Form2 should showing up. There're a few pixels distance between the Main Form and Form2.
Now what I need is when I move the Main Form to anywhere, then Form2 moves where ever Main Form goes. I mean I need Form2 to be lock on Main Form.
Have the MainForm override the virtual WndProc() method to reposition Form2 as needed relative to the MainForm's current position whenever a WM_WINDOWPOSCHANGING or WM_WINDOWPOSCHANGED message is received.
class TMainForm : public TForm
{
...
protected:
void __fastcall WndProc(TMessage &Message);
...
};
...
#include "Form2.h"
...
void __fastcall TMainForm::WndProc(TMessage &Message)
{
TForm::WndProc(Message);
switch (Message.Msg)
{
case WM_WINDOWPOSCHANGING:
case WM_WINDOWPOSCHANGED:
{
if ((Form2) && (Form2->Visible))
{
Form2->Left = ...; // such as this->Left
Form2->Top = ...; // such as this->Top + this->Height
}
break;
}
}
}
I had to remove all the default menus in blackberry. I have used the following code
protected void makeMenu(Menu menu, int instance) {
// if you want default menu items, uncomment bellow line
// super.makeMenu(menu, instance);
}
But after this, still it was showing the default menu like "Switch Application", for that i have used super(NO_SYSTEM_MENU_ITEMS) in the screen class constructor.
Now all menus are removed, but it is still showing "empty menu" as shown in the image below.
Please let me know how could we remove all menu items and make it empty?
try this in your main screen
public boolean onMenu(int instance) {
// TODO Auto-generated method stub
return false;
}
You can also do that.
public boolean onMenu(int instance) {
return super.onMenu(2);
}
Because for creating menu instance value is 0. So, for any non zero value it doesn't create the menu.