Basierend auf dem, was ich aus den anderen Antworten gelernt habe, konnte ich das funktionieren. Ich poste hier die Lösung für den Fall, dass es jemand anderes braucht.
Ich erstellte eine Komponente, MouseDownManager, die ich während des MouseDown-Ereignisses aufrufen. Er verfolgt die Taste, die gerade gedrückt wurde, bestimmt, auf welche Taste wir warten, um ein "beide" Tasten herunterzufahren, und startet dann einen Timer, um auf diese Taste zu warten. Wenn innerhalb der vorgegebenen Zeit die richtige Taste gedrückt wird, löst der MouseDownManager das entsprechende "bottom button down" -Ereignis aus. Andernfalls wird das entsprechende Einzelknopf-Ereignis ausgelöst. Auf dem Formular bearbeite ich das MouseDown-Ereignis des MouseDownManagers, um auf den übersetzten Mausklick einzugehen.
Ich kann jetzt nur diese Komponente auf ein Formular/Steuerelement fallen lassen und ich kann auf einen "beide" klicken.
Vielen Dank für die Hilfe, dies herauszufinden.
/// <summary>
/// Manage mouse down event to enable using both buttons at once.
/// I.e. allowing the pressing of the right and left mouse
/// buttons together.
/// </summary>
public partial class MouseDownManager : Component
{
/// <summary>
/// Raised when a mouse down event is triggered by this
/// component.
/// </summary>
public event EventHandler<MouseEventArgs> MouseDown;
protected virtual void OnMouseDown(MouseEventArgs e)
{
if (this.MouseDown != null)
{
this.MouseDown(this, e);
}
}
public MouseDownManager()
{
//-- the timer was dropped on the designer, so it
// is initialized by InitializeComponent.
InitializeComponent();
}
/// <summary>
/// Defines the interval that the timer will wait for the other
/// click, in milliseconds.
/// </summary>
public int BothClickInterval
{
get
{
return this.tmrBothInterval.Interval;
}
set
{
this.tmrBothInterval.Interval = value;
}
}
private MouseButtons _virtualButton = MouseButtons.Middle;
/// <summary>
/// Defines the button that is sent when both buttons are
/// pressed. This can be either a single button (like a middle
/// button) or more than one button (like both the left and
/// right buttons.
/// </summary>
public MouseButtons VirtualButton
{
get
{
return _virtualButton;
}
set
{
_virtualButton = value;
}
}
private MouseEventArgs _originalArgs;
/// <summary>
/// Defines the original mouse event arguments that is associated
/// with the original press.
/// </summary>
private MouseEventArgs OriginalArgs
{
get
{
return _originalArgs;
}
set
{
_originalArgs = value;
}
}
private MouseButtons _waitButton = MouseButtons.None;
/// <summary>
/// Defines the button that we are waiting on, for there to be a
/// both button click.
/// </summary>
private MouseButtons WaitButton
{
get
{
return _waitButton;
}
set
{
_waitButton = value;
}
}
/// <summary>
/// Manage a mouse button being depressed.
/// </summary>
/// <remarks>
/// This will instigate one of two actions. If there is no
/// current wait button, this will set the appropriate wait
/// button (if the button pressed was the left button, then we
/// are waiting on the right button) and start a timer. If the
/// wait button is set, but this isn't that button, then the wait
/// button is updated and the timer restarted. Also, this will
/// trigger the waiting event. If it is the wait button, then
/// the appropriate event is raised for a "both" button press.
/// </remarks>
public void ManageMouseDown(MouseEventArgs mouseArgs)
{
//-- Is the the button we are waiting for?
if (mouseArgs.Button == this.WaitButton)
{
//-- Turn off timer.
this.ClearTimer();
//-- Create new mouse event args for our virtual event.
MouseEventArgs bothArgs = new MouseEventArgs(this.VirtualButton
, mouseArgs.Clicks
, mouseArgs.X
, mouseArgs.Y
, mouseArgs.Delta);
//-- Raise the mouse down event.
this.OnMouseDown(bothArgs);
}
else
{
//-- Clear timer
this.ClearTimer();
//-- If we were waiting for a button, then
// fire the event for the original button.
if (this.WaitButton != MouseButtons.None)
{
this.OnMouseDown(this.OriginalArgs);
}
//-- Cache the original mouse event args.
MouseEventArgs newMouseArgs = new MouseEventArgs(mouseArgs.Button
, mouseArgs.Clicks
, mouseArgs.X
, mouseArgs.Y
, mouseArgs.Delta);
this.OriginalArgs = newMouseArgs;
//-- Reset to wait for the appropriate next button.
switch (mouseArgs.Button)
{
case MouseButtons.Left:
this.WaitButton = MouseButtons.Right;
break;
case MouseButtons.Right:
this.WaitButton = MouseButtons.Left;
break;
default:
this.WaitButton = MouseButtons.None;
break;
}
//-- Start timer
this.tmrBothInterval.Enabled = true;
}
}
/// <summary>
/// Raise the event for the button that was pressed initially
/// and turn off the timer.
/// </summary>
private void tmrBothInterval_Tick(object sender, EventArgs e)
{
//-- Turn off the timer.
this.tmrBothInterval.Enabled = false;
//-- Based on the original button pressed, raise
// the appropriate mouse down event.
this.OnMouseDown(this.OriginalArgs);
//-- Clear timer.
this.ClearTimer();
}
/// <summary>
/// Clear the timer and associated variables so we aren't waiting
/// for the second click.
/// </summary>
private void ClearTimer()
{
//-- Turn off the timer.
this.tmrBothInterval.Enabled = false;
//-- Clear the wait button.
this.WaitButton = MouseButtons.None;
//-- Clear the original args
this.OriginalArgs = null;
}
}
/// <summary>
/// Just the mouse code from the control needing the functionality.
/// </summary>
public class MyControl: Control
{
/// <summary>
/// Handle the mouse down event. This delegates the actual event
/// to the MouseDownManager, so we can capture the situation
/// where both buttons are clicked.
/// </summary>
protected override void OnMouseDown(MouseEventArgs e)
{
this.mdmMain.ManageMouseDown(e);
}
/// <summary>
/// Process the mouse down event.
/// </summary>
private void mdmMain_MouseDown(object sender, MouseEventArgs e)
{
//-- Get the reported button state.
MouseButtons mouseButton = e.Button;
//-- Execute logic based on button pressed, which now can include
// both the left and right together if needed....
}
}
Mann. Geh nicht dorthin. UI-Standards gibt es aus gutem Grund. Ihre Benutzerfreundlichkeit wird leiden. Das klingt schlimmer als der "Triple Click" – JohnFx
@ JohnFx Jeder anständige Minesweeper-Klon benötigt beide für das Akkordklopfen. Das ist ein Beispiel, wo es nützlich ist. – mbomb007