.net 如何检测左右按钮是否同时按下?
我想在一个控件上有三个鼠标操作:左、右和两者 我有左键和右键,目前正在使用第三个中键,但我很好奇,如果用户的鼠标没有中键,我怎么能同时使用左键和右键。这将在自定义控件的OnMouseDown方法中处理 更新 在回顾了建议的答案之后,我需要澄清,我试图做的是在MouseDown事件(实际上是控件的OnMouseDown方法)中对鼠标单击执行操作。因为当鼠标上的左键和右键都被单击时,.NET似乎总是会引发两个MouseDown事件(每个按钮一个),所以我猜唯一的方法是执行一些低级windows消息管理,或者在MouseDown之后执行某种延迟的操作。最后,使用鼠标中键更简单 现在,如果行动发生在MouseUp身上,那么Gary或nos的建议会很有效.net 如何检测左右按钮是否同时按下?,.net,click,mouseevent,mouse,.net,Click,Mouseevent,Mouse,我想在一个控件上有三个鼠标操作:左、右和两者 我有左键和右键,目前正在使用第三个中键,但我很好奇,如果用户的鼠标没有中键,我怎么能同时使用左键和右键。这将在自定义控件的OnMouseDown方法中处理 更新 在回顾了建议的答案之后,我需要澄清,我试图做的是在MouseDown事件(实际上是控件的OnMouseDown方法)中对鼠标单击执行操作。因为当鼠标上的左键和右键都被单击时,.NET似乎总是会引发两个MouseDown事件(每个按钮一个),所以我猜唯一的方法是执行一些低级windows消息管
如果您对这个问题有进一步的了解,我们将不胜感激。谢谢 不确定是否有本机的.Net方法,但如果您对p/Invoke感到满意,您可以使用或类似以下方法:
[DllImport("user32.dll")]
public static extern short GetKeyState(int nVirtKey);
if (GetKeyState((int)Keys.LButton) < 0 && GetKeyState((int)Keys.RButton) < 0)
{
// Both buttons are pressed.
}
[DllImport(“user32.dll”)]
公共静态外部短GetKeyState(int nVirtKey);
if(GetKeyState((int)Keys.LButton)<0&&GetKeyState((int)Keys.RButton)<0)
{
//两个按钮都按下了。
}
难道“中间”和“左右并排”不一样吗?至少这是我在某处记得的,但那是很久以前的事了,当时我有两个没有滚轮按钮的按钮鼠标…总是有“自己动手”的方法:
只需记住按钮按下和释放的状态。在OnMouseDown中,您只需记住按下的按钮,而在OnMouseUp中,只需检查记住了哪些按钮,并清除按钮的状态
释放按钮时,您需要一些逻辑来避免执行多个操作。
差不多
MouseButtons buttonPressed;
..
void OnMouseDown(MouseEventArgs e)
{
buttonPressed |= e.Button;
}
void OnMouseUp(MouseEventArgs e)
{
if(!doneAction) {
if((buttonPressed & MouseButtons.Right == MouseButtons.Right
&& buttonPressed & MouseButtons.Left == MouseButtons.Left)
|| buttonPressed & MouseButtons.Middle== MouseButtons.Middle) {
DoMiddleAction();
doneAction = true;
} else if(check Right button , etc.) {
....
}
}
buttonpressed &= ~e.Button;
if(buttonpressed == None)
doneAction = false;
}
我个人会使用
MouseUp
和MouseDown
事件来更干净地处理它,避免互操作。基本上,这段代码使用一个静态类来保持这两个按钮的状态,并通过检查可以确定这两个按钮是否都处于关闭状态
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public static class MouseButtonStatus
{
static bool RightButton;
static bool LeftButton;
public static bool RightButtonPressed
{
get
{
return RightButton;
}
set
{
RightButton = value;
}
}
public static bool LeftButtonPressed
{
get
{
return LeftButton;
}
set
{
LeftButton = value;
}
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void HandleButtons(bool LeftPressed, bool RightPressed)
{
if(LeftPressed && RightPressed)
{
//BOTH ARE PRESSED
}
else if(LeftPressed)
{
//LEFT IS PRESSED
}
else if(RightPressed)
{
//RIGHT IS PRESSED
}
else
{
//NONE ARE PRESSED
}
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
{
MouseButtonStatus.LeftButtonPressed = true;
}
if(e.Button == MouseButtons.Right)
{
MouseButtonStatus.RightButtonPressed = true;
}
HandleButtons(MouseButtonStatus.LeftButtonPressed, MouseButtonStatus.RightButtonPressed);
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
{
MouseButtonStatus.LeftButtonPressed = false;
}
if(e.Button == MouseButtons.Right)
{
MouseButtonStatus.RightButtonPressed = false;
}
HandleButtons(MouseButtonStatus.LeftButtonPressed, MouseButtonStatus.RightButtonPressed);
}
}
}
根据我从其他答案中学到的知识,我能够让它工作。我在这里发布解决方案,以防其他人需要它 我创建了一个组件MouseDownManager,在MouseDown事件期间调用它。它跟踪刚刚按下的按钮,确定我们正在等待的按钮,以便有一个“两个”按钮关闭事件,然后启动计时器等待该按钮。如果在分配的时间内按下了正确的按钮,MouseDownManager将引发相应的“同时按下”按钮事件。否则将引发相应的单按钮事件。在表单上,我正在处理MouseDownManager的MouseDown事件,以便对转换后的鼠标单击执行操作 我现在可以把这个组件放到一个窗体/控件上,我可以对“两者”的点击做出反应 谢谢你帮我弄明白这件事
/// <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....
}
}
//
///管理鼠标按下事件以启用同时使用两个按钮。
///即,允许按下鼠标右键和左键
///把钮扣扣在一起。
///
公共部分类MouseDownManager:组件
{
///
///当此事件触发鼠标按下事件时引发
///组成部分。
///
公共事件处理程序MouseDown;
MouseEventArgs e上受保护的虚拟空间
{
如果(this.MouseDown!=null)
{
this.MouseDown(this,e);
}
}
公共鼠标下载管理器()
{
//--计时器掉在了设计器上,所以它
//由InitializeComponent初始化。
初始化组件();
}
///
///定义计时器等待另一个计时器的时间间隔
///单击,以毫秒为单位。
///
公共int BothClickInterval
{
得到
{
返回this.tmrBothInterval.Interval;
}
设置
{
this.tmrBothInterval.Interval=值;
}
}
私有鼠标按钮_virtualButton=MouseButtons.Middle;
///
///定义当两个按钮都被选中时发送的按钮
///按下。这可以是单个按钮(如中间按钮)
///按钮)或多个按钮(如左键和右键)
///右键。
///
公共鼠标按钮虚拟按钮
{
得到
{
返回虚拟按钮;
}
设置
{
_虚拟按钮=值;
}
}
私用鼠标;原始标记;
///
///定义关联的原始鼠标事件参数
///与最初的媒体。
///
私用MouseEventArgs OriginalArgs
{
得到
{
返回原始标记;
}
设置
{
_originalArgs=值;
}
}
私有鼠标按钮_waitButton=MouseButtons.None;
///
///定义我们正在等待的按钮,以便
///两个按钮都单击。
///
专用鼠标按钮等待按钮
{
得到
{
返回等待按钮;
}
设置
{
_waitButton=值;
}
}
///
///管理被按下的鼠标按钮。
///
///
///这将引发两种行为之一。如果没有
///当前等待按钮,这将设置适当的等待
///按钮(如果按下的按钮是左按钮,则我们
///正在等待右键)并启动计时器。如果
///等待按钮已设置,但这不是该按钮,然后等待
///按钮更新,计时器重新启动。同时,这将
///触发等待事件。如果是等待按钮,则
///按下“两个”按钮会引发相应的事件。
///
public void managed mousedown(MouseEventArgs mouseArgs)
{
//--这是我们正在等的按钮吗?
if(mouseArgs.Button==此.WaitButton)
{
//--关闭计时器
bool midL,midR;
private void form1_MouseUp(object sender, MouseEventArgs e)
{
midL = false;
midR = false;
}
private void form1_MouseDown(object sender, MouseEventArgs e)
{
if (!midL)
midL = e.Button == MouseButtons.Left;
if (!MidR)
midR = e.Button == MouseButtons.Right;
if (e.Button == MouseButtons.Middle || (midL && midR))
{
MessageBox.show("Middle button is pressed")
}
}