How to focus a certain tabpage when it rightclicked? - c#

How to select or focus a certain tabpage when it right clicked?

Implement the MouseDown event and find out what tab got clicked:
private void tabControl1_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Right) {
for (int tab = 0; tab < tabControl1.TabCount; ++tab) {
if (tabControl1.GetTabRect(tab).Contains(e.Location)) {
tabControl1.SelectedIndex = tab;
break;
}
}
}
}

Related

Visual C# ListView ContextMenu

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.

Determining which tabpage has opened

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();
}

Select row in DataGridView in mouse_click event

I have a DataGridView on a form. When I right-click a row, I need the program to open a context menu. With this context menu I want to be able to modify the data in the DataGridView.
I have gotten the context menu to show where I right click, but I don't know where to go from here. As I will be deleting (for example) an entire row, I need to get the index of said row and also set it to selected. I tried this with the cell_clicked event but I can't determine if the left or right mouse button was pressed. But with the mouse_click event I cannot get the row index.
Here is my code:
public Form()
{
ContextMenu contextMenu = new ContextMenu();
//Fill Context Menu
MenuItem delete = new MenuItem("Delete");
contextMenu.MenuItems.Add(delete);
}
private void grdSchedules_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
contextMenu.Show(grdSchedules, new Point(e.Y, e.Y));
//Get rowindex here and select row
}
}
I have tried it this way:
private void grdSchedules_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right) //e.Button does not work here
{
contextMenu.Show(grdSchedules, new Point(e.Y, e.Y));
}
}
I created a more simple and faster generic method which works with any datagrids. This method allows selecting rows with a right click. Add this method to your DataGridViews' "MouseDown" event:
public void DataGridView_RightMouseDown_Select(object sender, MouseEventArgs e)
{
// If the user pressed something else than mouse right click, return
if (e.Button != System.Windows.Forms.MouseButtons.Right) { return; }
DataGridView dgv = (DataGridView)sender;
// Use HitTest to resolve the row under the cursor
int rowIndex = dgv.HitTest(e.X, e.Y).RowIndex;
// If there was no DataGridViewRow under the cursor, return
if (rowIndex == -1) { return; }
// Clear all other selections before making a new selection
dgv.ClearSelection();
// Select the found DataGridViewRow
dgv.Rows[rowIndex].Selected = true;
}
I have found a solution. Here is how I did it:
private void grdSchedules_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
int currentMouseOverRow = grdSchedules.HitTest(e.X, e.Y).RowIndex;
for (int x = 0; x < grdSchedules.Rows.Count; x++)
{
if (grdSchedules.Rows[x].Index == currentMouseOverRow)
{
grdSchedules.Rows[x].Selected = true;
}
else
{
grdSchedules.Rows[x].Selected = false;
}
}
contextMenu.Show(grdSchedules, new Point(e.Y, e.Y));
}
}
You could've used grdSchedules_MouseDown or grdSchedules_MouseUp events instead of grdSchedules_MouseClick or grdSchedules_CellClick.

How to put a ContextMenu into the header of a TabPage

I have a custom TabControl in which I have TabPages with ContextMenu bound to them.
I want the menu to show up only when the page header is being clicked.
What I do is that, when the TabControl is clicked, I check these conditions:
private void MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == Mousebuttons.Right)
{
for (int i = 0; i < TabCount; ++i)
{
Rectangle r = GetTabRect(i);
if (r.Contains(e.Location) /* && it is the header that was clicked*/)
{
// Change slected index, get the page, create contextual menu
ContextMenu cm = new ContextMenu();
// Add several items to menu
page.ContextMenu = cm;
page.ContextMenu.Show(this, e.Location);
}
}
}
}
If I bind MouseUp to the TabControl, I get the ContextMenu in the entire TabPage. If I bind it to the TabPage, I only get the ContextMenu in the body and not in the header.
Is there a way to have a ContextMenu to show up only on header Click ?
Just don't ever assign the ContextMenu to anything...simply display it:
public class MyTabControl : TabControl
{
protected override void OnMouseUp(MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
for (int i = 0; i < TabCount; ++i)
{
Rectangle r = GetTabRect(i);
if (r.Contains(e.Location) /* && it is the header that was clicked*/)
{
// Change slected index, get the page, create contextual menu
ContextMenu cm = new ContextMenu();
// Add several items to menu
cm.MenuItems.Add("hello");
cm.MenuItems.Add("world!");
cm.Show(this, e.Location);
break;
}
}
}
base.OnMouseUp(e);
}
}
Instead of override like Idle_Mind said, you could also do the same with a normal tabcontrol on the mouseevent:
private void tabControl1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
for (int i = 0; i < tabControl1.TabCount; ++i)
{
Rectangle r = tabControl1.GetTabRect(i);
if (r.Contains(e.Location) /* && it is the header that was clicked*/)
{
// Change slected index, get the page, create contextual menu
ContextMenu cm = new ContextMenu();
// Add several items to menu
cm.MenuItems.Add("hello");
cm.MenuItems.Add("world!");
cm.Show(tabControl1, e.Location);
break;
}
}
}
}
It does exactly the same, but doesn't add an extra control in your toolbox:)
You could also make it generic if you want to use it on multiple TabControls.
private void showContextMenu_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
TabControl tabControl1 = sender as TabControl;
[...]

Close tab on winforms tab control with middle mouse button

Is there any easy (5 lines of code) way to do this?
The shortest code to delete the tab the middle mouse button was clicked on is by using LINQ.
Make sure the event is wired up
this.tabControl1.MouseClick += tabControl1_MouseClick;
And for the handler itself
private void tabControl1_MouseClick(object sender, MouseEventArgs e)
{
var tabControl = sender as TabControl;
var tabs = tabControl.TabPages;
if (e.Button == MouseButtons.Middle)
{
tabs.Remove(tabs.Cast<TabPage>()
.Where((t, i) => tabControl.GetTabRect(i).Contains(e.Location))
.First());
}
}
And if you are striving for least amount of lines, here it is in one line
tabControl1.MouseClick += delegate(object sender, MouseEventArgs e) { var tabControl = sender as TabControl; var tabs = tabControl.TabPages; if (e.Button == MouseButtons.Middle) { tabs.Remove(tabs.Cast<TabPage>().Where((t, i) => tabControl.GetTabRect(i).Contains(e.Location)).First()); } };
Solution without LINQ not so compact and beautiful, but also actual:
private void TabControlMainMouseDown(object sender, MouseEventArgs e)
{
var tabControl = sender as TabControl;
TabPage tabPageCurrent = null;
if (e.Button == MouseButtons.Middle)
{
for (var i = 0; i < tabControl.TabCount; i++)
{
if (!tabControl.GetTabRect(i).Contains(e.Location))
continue;
tabPageCurrent = tabControl.TabPages[i];
break;
}
if (tabPageCurrent != null)
tabControl.TabPages.Remove(tabPageCurrent);
}
}
Don't have enough points to post a comment to the provided solutions but they all suffer from the same flaw: The controls within the removed tab are not released.
Regards
You could do this:
private void tabControl1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Middle)
{
// choose tabpage to delete like below
tabControl1.TabPages.Remove(tabControl1.TabPages[0]);
}
}
Basically you are just catching a mouse click on tab control and only deleting a page if the middle button was clicked.

Categories

Resources