Pass-through eventos de mouse para controle pai
-
23-08-2019 - |
Pergunta
Ambiente:. .NET Framework 2.0, o VS 2008
Eu estou tentando criar uma subclasse de certos controles .net (rótulo, painel) que passarão através de determinados eventos de mouse (MouseDown
, MouseMove
, MouseUp
) para o controle pai (ou, em alternativa ao formulário de nível superior). Eu posso fazer isso criando manipuladores para esses eventos em instâncias dos controles padrão, p.ex.:.
public class TheForm : Form
{
private Label theLabel;
private void InitializeComponent()
{
theLabel = new Label();
theLabel.MouseDown += new MouseEventHandler(theLabel_MouseDown);
}
private void theLabel_MouseDown(object sender, MouseEventArgs e)
{
int xTrans = e.X + this.Location.X;
int yTrans = e.Y + this.Location.Y;
MouseEventArgs eTrans = new MouseEventArgs(e.Button, e.Clicks, xTrans, yTrans, e.Delta);
this.OnMouseDown(eTrans);
}
}
Eu não posso mover o manipulador de eventos em uma subclasse do controle, porque os métodos que aumentam os eventos no controle pai estão protegidos e não tenho um qualificador para o controle pai:
Não é possível acesso protegido
System.Windows.Forms.Control.OnMouseDown(System.Windows.Forms.MouseEventArgs)
membro através de um qualificador do tipoSystem.Windows.Forms.Control
; o qualificador deve ser do tipoTheProject.NoCaptureLabel
(ou derivado dele).
Eu estou olhando para substituir o método WndProc
do controle no meu sub-classe, mas espero que alguém pode me dar uma solução mais limpa.
Solução
Sim. Depois de muita pesquisa, descobri o artigo "Controls Flutuante, dica de estilo" , que usa WndProc
para alterar a mensagem de WM_NCHITTEST
para HTTRANSPARENT
, tornando o Control
transparente para eventos do mouse.
Para conseguir isso, criar um controle herdado de Label
e simplesmente adicione o seguinte código.
protected override void WndProc(ref Message m)
{
const int WM_NCHITTEST = 0x0084;
const int HTTRANSPARENT = (-1);
if (m.Msg == WM_NCHITTEST)
{
m.Result = (IntPtr)HTTRANSPARENT;
}
else
{
base.WndProc(ref m);
}
}
Eu testei isso no Visual Studio 2010 com o .NET Framework 4 Client Profile.
Outras dicas
Você precisa escrever um método público / protegido em sua classe base que irá aumentar o evento para você. Em seguida, chamar esse método de classe derivada.
ou
É isso que você quer?
public class MyLabel : Label
{
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
//Do derived class stuff here
}
}
O WS_EX_TRANSPARENT
estendido estilo da janela realmente faz isso (é o que in-place dicas usar). Você pode querer considerar a aplicação deste estilo, em vez de codificação de lotes de manipuladores de fazê-lo para você.
Para fazer isso, substituir o método CreateParams
:
protected override CreateParams CreateParams
{
get
{
CreateParams cp=base.CreateParams;
cp.ExStyle|=0x00000020; //WS_EX_TRANSPARENT
return cp;
}
}
Para ler mais: