I have a contextmenustrip that contains some option, I have almost implemented everything, i just want to check which items i have selected in options_MouseClick
private void ConsoleRichTextBox_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
options.Show();
Point currentPoint;
currentPoint = new Point(e.X, e.Y);
options.Show(ConsoleRichTextBox, currentPoint);
}
}
private void options_MouseClick(object sender, MouseEventArgs e)
{
//if options selected = clear
ConsoleRichTextBox.Clear();
}
You should just handle the Click event of each of the menu items. There's no need to handle the MouseClick event of a contextmenustrip. Also you can add multiple handlers to the same method and differentiate with the sender parameter as this will refer to the exact menu item that was clicked.
ToolStripMenuItem tsmi = new ToolStripMenuItem();
tsmi.Click += tsmi_Click;
and:
public void tsmi_Click(object sender, EventArgs e)
{
if (sender == tsmi)
{
// Do stuff
}
}
Related
Im trying to open a new form when a label is double clicked. Im able to drag and drop the label .Im trying to open a new form on double click of label now.
private void control_MouseDown(object sender, MouseEventArgs e)
{
var control = sender as Control;
this.DoDragDrop(control.Name, DragDropEffects.Move);
}
private void control_DoubleClick(object sender, EventArgs e)
{
frm = new Frm();
frm.ShowDialog();
frm.Dispose();
}
EDIT 1:
I have tried both possible answers below, and they have not worked for me?
A more cleaner way is (note I changed Frm to Form1):
private void control_DoubleClick(object sender, EventArgs e)
{
using (Form1 frm = new Form1())
{
frm.ShowDialog();
}
}
You can't add DragDrop on MouseDown and then DoubleClick. That won't work.
I don't think there's an easy way to get around that, but once a control is being dragged, it won't respond to double click messages.
I've made some quick tests, and there's a "hacky" way. It'll make your dragging look weird (since it'll start after some time, instead of immediately after you press the mouse button), but here it goes:
private bool _willDrag = false;
private bool control_MouseUp(object sender, MouseEventArgs e)
{
// disable dragging if we release the mouse button
_willDrag = false;
}
private bool control_DoubleClick(object sender, EventArgs e)
{
// disable dragging also if we double-click
_willDrag = false;
// .. the rest of your doubleclick event ...
}
private void control_MouseDown(object sender, MouseEventArgs e)
{
var control = sender as Control;
if (control == null)
return;
_willDrag = true;
var t = new System.Threading.Timer(s =>
{
var callingControl = s as Control;
if (callingControl == null)
return;
// if we released the mouse button or double-clicked, don't drag
if(!_willDrag)
return;
_willDrag = false;
Action x = () => DoDragDrop(callingControl.Name, DragDropEffects.Move);
if (control.InvokeRequired)
control.Invoke(x);
else
x();
}, control, SystemInformation.DoubleClickTime, Timeout.Infinite);
}
In the form.Designer right click on your label then properties, in the properties window click in events (the thunder icon), in the double_Click event dropdown select the event handler (control_DoubleClick) this method must have two parameters an object and a eventArgs
This is tricky as the DoDragDrop will eat up any further mouse events, and MSDN posting a rather stupid example doesn't help much.
Solution: Do not start the D&D in the MouseDown if you want to still receive click or double click events but use the MouseMove instead:
Replace this
private void control_MouseDown(object sender, MouseEventArgs e)
{
var control = sender as Control;
this.DoDragDrop(control.Name, DragDropEffects.Move);
}
by this:
private void control_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
DoDragDrop((sender as Control), DragDropEffects.Move);
}
Don't forget to hook up the new event!
I have a ListView to display Images Icons, and i need 2 different Context menu on that ListView that have to show when i Right Click inside the ListView.
ContextMenu1 have to show only when i Right Click on a Item
ContextMenu2 have to show when i DO NOT Right click on a Item, but in the blank space of the ListView.
This is the current Code that i have, but it is only working when i right click on a item:
private void ListView_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
if (ListView.GetItemAt(e.X, e.Y) is ListViewItem)
{
ContextMenu1.Show(Cursor.Position);
}
else
{
ContextMenu2.Show(Cursor.Position);
}
}
}
What i did wrong?
GetItemAt will always return a ListviewItem. You should check for null like this example from MSDN:
private void ListView_MouseDown(object sender, MouseEventArgs e)
{
if (ListView.GetItemAt(e.X, e.Y) != null )
{
ContextMenu1.Show(Cursor.Position);
}
else
{
ContextMenu2.Show(Cursor.Position);
}
}
Try using the MouseDown or MouseUp event instead:
listView1.MouseDown += listView1_MouseDown;
void listView1_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Right) {
if (listView1.GetItemAt(e.X, e.Y) is ListViewItem) {
ContextMenu1.Show(Cursor.Position);
} else {
ContextMenu2.Show(Cursor.Position);
}
}
}
The MouseClick event fires only when a ListItem is clicked.
I'm trying to get the tabpage that was clicked by right button of mouse,in another words the tabpage that opened the contextmenustrip.
There's a toolstripmenuitem called Close which I used to close the tab that was clicked on.
I used this code :
public partial class USBrowser : Form
{
private Point lastpoint;
}
private void closeTabToolStripMenuItem_Click(object sender, EventArgs e)
{
for (int i = 0; i < browserTabControl.TabCount; i++)
{
Rectangle rec = browserTabControl.GetTabRect(i);
if (rec.Contains(this.PointToClient(lastpoint)))
closeTab(i);//this function closes the tab at specific index
}
}
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
if (e.Button == MouseButtons.Right)
lastpoint = Cursor.Position;
}
I also added(when adding the tabpage) :
browserTabControl.TabPages.Insert(browserTabControl.TabCount - 1,WebPage);
browserTabControl.SelectTab(WebPage);
browserTabControl.SelectedTab.MouseClick += SelectedTab_MouseClick;
void SelectedTab_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
lastpoint = Cursor.Position;
}
The problem is that the lastpoint is always (0,0) !!
Why ?
Any other suggested idea is welcomed
thanx in advance
None of these event handlers will actually run. Not the form's OnMouseClick() method since you are not actually right-clicking the form. And not the tab page's MouseClick event handler since you gave the TabControl a context menu. So lastpoint being empty is the expected outcome.
It is not clear how you want this context menu to work. If you use it by right-clicking the tab page then it is simple, just destroy the selected page:
private void closeToolStripMenuItem_Click(object sender, EventArgs e) {
tabControl1.SelectedTab.Dispose();
}
If you activate it by right-clicking a tab, one that isn't selected, then it gets more complicated. You have to memorize which tab was clicked on, do so by using the context menu's Opening event:
private TabPage RightClickedTab;
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) {
RightClickedTab = tabControl1.SelectedTab;
var pos = tabControl1.PointToClient(Cursor.Position);
for (int tab = 0; tab < tabControl1.TabCount; ++tab) {
if (tabControl1.GetTabRect(tab).Contains(pos)) {
RightClickedTab = tabControl1.TabPages[tab];
break;
}
}
}
private void closeToolStripMenuItem_Click(object sender, EventArgs e) {
if (RightClickedTab != null) RightClickedTab.Dispose();
}
Problem
I have two ListView's. One has options that are to be dragged into the other. This is the "fields" ListView. The other one is the "builder" ListView. I cannot figure out a way to visually show the user where the item will be inserted. I would like to draw a line in-between the ListViewItem's to visually aid the user.
private void builder_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
private void fields_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
private void fields_ItemDrag(object sender, ItemDragEventArgs e)
{
fromBuilder = false;
fields.DoDragDrop(e.Item, DragDropEffects.Move);
}
private void builder_ItemDrag(object sender, ItemDragEventArgs e)
{
fromBuilder = true;
builder.DoDragDrop(e.Item, DragDropEffects.Move);
}
private void builderAndFields_DragDrop(object sender, DragEventArgs e)
{
ListViewItem i = new ListViewItem();
i = e.Data.GetData(typeof(ListViewItem)) as ListViewItem;
// Since this function works for both the builder and the fields,
// we have to check to see where we are dropping, the sender
// is the ListView we are dropping onto
if (sender.Equals(builder))
{
ListViewItem c = new ListViewItem();
c = (ListViewItem)i.Clone();
Point cp = builder.PointToClient(new Point(e.X, e.Y));
Console.WriteLine("cp: " + cp);
ListViewItem dragToItem = builder.GetItemAt(cp.X, cp.Y);
Console.WriteLine("dragToItem: " + dragToItem);
int dropIndex = dragToItem.Index;
// Now, we have to check to see if we are reordering or adding
// So, we check the flag to see if the dragDrop was initiated
// on the builder or on the fields ListView
if (fromBuilder)
{
builder.Items.Insert(dropIndex, c);
builder.Items.Remove(i);
}
else
{
Console.WriteLine(dropIndex);
builder.Items.Insert(dropIndex, c);
}
}
// If the sender is the fields listView, the user is trying to remove
// the item from the builder.
else
{
builder.Items.Remove(i);
}
}
Take a look at PreviewDragEnter, PreviewDragOver, and PreviewDragLeave.
You can use that event to add an Adorner to your drop list. IF you search for "WPF DragDropHelper" you will find several detailed examples.
Better ListView supports drop highlighting and insertion marks out of the box:
I think you can also do this in a regular ListView using HitTest() method within DragOver event handler.
I would like to extended DataGridView to add a second ContextMenu which to select what columns are visible in the gird. The new ContextMenu will be displayed on right click of a column's header.
I am having difficulty get the correct horizontal position to show the context menu. How can I correct this?
public partial class Form1 : Form
{
DataGridView dataGrid;
ContextMenuStrip contextMenuStrip;
public Form1()
{
InitializeComponent();
dataGrid = new DataGridView();
Controls.Add(dataGrid);
dataGrid.Dock = System.Windows.Forms.DockStyle.Fill;
dataGrid.ColumnHeaderMouseClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(ColumnHeaderMouseClick);
dataGrid.DataSource = new Dictionary<string, string>().ToList();
contextMenuStrip = new ContextMenuStrip();
contextMenuStrip.Items.Add("foo");
contextMenuStrip.Items.Add("bar");
}
private void ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
contextMenuStrip.Show(PointToScreen(e.Location));
}
}
}
Here is a very simple way to make context menu appear where you right-click it.
Handle the event ColumnHeaderMouseClick
private void grid_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
contextMenuHeader.Show(Cursor.Position);
}
contextMenuHeader is a ContextMenuStrip that can be defined in the Designer view or at runtime.
To get the coordinate of the mouse cursor you could do this.
ContextMenu.Show(this, myDataGridView.PointToClient(Cursor.Position));
Have you tried using the Show overload that accepts a control and a position?
For example:
contextMenuStrip.Show(dataGrid, e.Location);
Edit: Full example
public partial class Form1 : Form
{
DataGridView dataGrid;
ContextMenuStrip contextMenuStrip;
public Form1()
{
InitializeComponent();
dataGrid = new DataGridView();
Controls.Add(dataGrid);
dataGrid.Dock = System.Windows.Forms.DockStyle.Fill;
dataGrid.MouseDown += MouseDown;
dataGrid.DataSource = new Dictionary<string, string>().ToList();
contextMenuStrip = new ContextMenuStrip();
contextMenuStrip.Items.Add("foo");
contextMenuStrip.Items.Add("bar");
}
private void MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
if (dataGrid.HitTest(e.X, e.Y).Type == DataGridViewHitTestType.ColumnHeader)
{
contextMenuStrip.Show(dataGrid, e.Location);
}
}
}
}
e.Location does not show the popup menu at the correct coordinates, instead just use the MousePosition property as follows:
ContextMenuStrip.Show(MousePosition)
or, explicitely
ContextMenuStrip.Show(Control.MousePosition)
The position returned is relative to the cell. So we have to add that offset.
private void grdView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
var pos = ((DataGridView)sender).GetCellDisplayRectangle(e.ColumnIndex,
e.RowIndex, false).Location;
pos.X += e.X;
pos.Y += e.Y;
contextMenuStrip.Show((DataGridView)sender,pos);
}
}
Finally this worked for me.
ContextMenu.Show(myDataGridView, myDataGridView.PointToClient(Cursor.Position));
Calling Show twice will get you the exact location of the cursor. This answer is for those whom are unable to get the result with all above answers.
private void MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
contextMenuStrip.Show(dataGrid, e.Location));
contextMenuStrip.Show(Cursor.Position);
}
}
Where I was going wrong was that DataGridViewCellMouseEventArgs returns the location/x,y of where the mouse clicked within the column header. Instead I need to use HitTest in the grid's MouseDown event for a hit on the column headers and then convert the position of the hit from the gird co-ordinates to the screen co-ordinates.
public partial class Form1 : Form
{
DataGridView dataGrid;
ContextMenuStrip contextMenuStrip;
public Form1()
{
InitializeComponent();
dataGrid = new DataGridView();
Controls.Add(dataGrid);
dataGrid.Dock = System.Windows.Forms.DockStyle.Fill;
//dataGrid.ColumnHeaderMouseClick += ColumnHeaderMouseClick;
dataGrid.MouseDown += MouseDown;
dataGrid.DataSource = new Dictionary<string, string>().ToList();
contextMenuStrip = new ContextMenuStrip();
contextMenuStrip.Items.Add("foo");
contextMenuStrip.Items.Add("bar");
}
private void ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
contextMenuStrip.Show(PointToScreen(e.Location));
}
}
private void MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
if (dataGrid.HitTest(e.X, e.Y).Type == DataGridViewHitTestType.ColumnHeader)
{
contextMenuStrip.Show(dataGrid.PointToScreen(e.Location));
}
}
}
}
You were nearly right. You just need to the apply the PointToScreen method to the calling control:
private void ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
contextMenuStrip.Show(((DataGridView)sender).PointToScreen(e.Location));
}
}
I think this is the most elegant solution, because it uses only the ColumnHeaderMouseClick arguments and not Cursor.Position.