TabControl Context Menu
-
19-08-2019 - |
Pergunta
Em Windows Forms aplicativo que eu defina a propriedade ContextMenuStrip em um TabControl.
- Como posso dizer o usuário clicou em uma guia outros, então o que está selecionado no momento?
- Como posso restringir o menu de contexto de mostrar apenas quando o topo parte Tab com o rótulo é clicado, e não em outras partes do guia?
Solução
Não se preocupe em definir a propriedade ContextMenuStrip no TabControl. Em vez fazê-lo desta forma. Ligar para o evento MouseClick do tabControl, e depois mostrar manualmente o menu de contexto. Isso só será acionado se o próprio guia em cima é clicado, não a página real. Se você clicar na página, então o tabControl não recebe o evento de clique, o TabPage faz. Algum código:
public Form1()
{
InitializeComponent();
this.tabControl1.MouseClick += new MouseEventHandler(tabControl1_MouseClick);
}
private void tabControl1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
this.contextMenuStrip1.Show(this.tabControl1, e.Location);
}
}
Outras dicas
evento de abertura do menu de contexto pode ser usado para resolver ambos os problemas
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
Point p = this.tabControl1.PointToClient(Cursor.Position);
for (int i = 0; i < this.tabControl1.TabCount; i++)
{
Rectangle r = this.tabControl1.GetTabRect(i);
if (r.Contains(p))
{
this.tabControl1.SelectedIndex = i; // i is the index of tab under cursor
return;
}
}
e.Cancel = true;
}
Um pouco tarde, mas eu encontrei uma solução para a primeira parte da sua pergunta. Você pode descobrir qual guia foi clicado com o botão direito enviando um clique esquerdo do mouse para a aplicação. Isso seleciona a guia, então agora você pode usar a propriedade TabControl.SelectedTab para obter o guia que o usuário clicou com o botão direito.
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
private const int MOUSEEVENTF_RIGHTUP = 0x10;
private static void SendLeftMouseClick()
{
int x = Cursor.Position.X;
int y = Cursor.Position.Y;
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, x, y, 0, 0);
}
public Form1()
{
InitializeComponent();
tabControl1.MouseDown += new MouseEventHandler(tabControl1_MouseDown);
tabControl1.MouseUp += new MouseEventHandler(tabControl1_MouseUp);
}
void tabControl1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
// Send a left mouse click to select the tab that the user clicked on.
SendLeftMouseClick();
}
}
void tabControl1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
// To show a context menu for only the tab button but not the content of the tab,
// we must show it in the tab control's mouse up event.
contextMenuStrip1.Show((Control)sender, e.Location);
}
}
Eu estava procurando por uma solução para exatamente o mesmo problema.
Depois de testar tanto @nisar e @BFree responde Eu vim para isso (eu também tinha a TabControl` dentro de um lugar Painel no Formulário):
- Criar TabControl1
- Inscrever-se para o evento MouseClick
- Criar contextMenuTabs, ContextMenuStrip
private void tabControl1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
Point ee = new Point(e.Location.X - panel1.Left, e.Location.Y - panel1.Top);
for (int i = 0; i < this.tabControl1.TabCount; i++)
{
Rectangle r = this.tabControl1GetTabRect(i);
if (r.Contains(ee))
{
if (this.tabControl1.SelectedIndex == i)
this.contextMenuTabs.Show(this.tabControl1, e.Location);
else
{
//if a non seelcted page was clicked we detected it here!!
}
break;
}
}
}
}