Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 获取鼠标光标在表单外侧单击时的位置';s边界_C#_Mouse Position - Fatal编程技术网

C# 获取鼠标光标在表单外侧单击时的位置';s边界

C# 获取鼠标光标在表单外侧单击时的位置';s边界,c#,mouse-position,C#,Mouse Position,只需拖动鼠标,就可以很容易地将光标的位置移到窗体边界之外。当位置发生变化时,鼠标会向窗体发送许多值,如下代码行所示 MessageBox.Show(Cursor.Position.ToString()); 但我需要在用户单击表单边界外侧时获取鼠标位置。 不仅仅是鼠标悬停。我使用以下代码行来完成此操作: private void Form1_Deactivate(object sender, EventArgs e) { MessageBox.Show(Cursor.Position.

只需拖动鼠标,就可以很容易地将光标的位置移到窗体边界之外。当位置发生变化时,鼠标会向窗体发送许多值,如下代码行所示

MessageBox.Show(Cursor.Position.ToString());

但我需要在用户单击表单边界外侧时获取鼠标位置。 不仅仅是鼠标悬停。我使用以下代码行来完成此操作:

private void Form1_Deactivate(object sender, EventArgs e)
{
    MessageBox.Show(Cursor.Position.ToString());
}
我放置了MessageBox.Show(Cursor.Position.ToString())进入表单停用事件。当用户在表单外单击时,肯定会发生此事件。但当用户不单击外部,而是使用ALT+TAB组合键更改程序时,它也会发送错误的值

实际上,我必须从第一次单击的位置开始捕捉该区域的屏幕快照。因此,我需要在窗体外部单击光标时光标的位置。 比如:

您应该使用
全局鼠标挂钩
逻辑来执行此操作


这里有一篇很好的文章可以帮助您:

停用事件通知您的表单它不再处于活动状态。这可能是因为很多原因


通常,只有当鼠标位于窗口上方时,窗口才会获取鼠标事件。该函数允许您捕获所有鼠标事件(我不知道.NET对应项)。因为只有一个窗口可以捕获鼠标事件,所以不应该在不需要时捕获鼠标事件。这个问题没有足够的细节来说明您真正想做什么,以及用户在表单外单击时为什么需要知道。

这可能会对某些人有所帮助

这里我使用了
Windows.Forms.Timer
和两个文本框来显示[X和Y]光标位置。在计时器上勾选调用API
GetCursorPos
并获取光标位置

public partial class Form1 : Form
{
    [DllImport("user32.dll")]
    static extern bool GetCursorPos(ref Point lpPoint);

    public Form1()
    {
        InitializeComponent();
        timer1.Start();
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        var pt = new Point();

        GetCursorPos(ref pt);
        textBox1.Text = pt.X.ToString();
        textBox2.Text = pt.Y.ToString();
    }   
}
问候,,
兰吉特。

这个问题的解决办法很简单。您所需要的只是一个
System.Windows.Forms.Timer
,并使用
System.Runtime.InteropService.DllImport
从user32.dll中导出方法
GetKeyState

此函数有一个任意类型的整数参数,并返回short(Int16)。此功能可以告诉您是否在任何时候、任何地方都按了某些键,而不取决于表单。启用计时器时,可以检查鼠标位置是否超出窗体边界。有很多方法可以获得鼠标位置

一种方法是
Cursor.Position
,或者
Control.MousePosition
,或者您可以使用bool
GetCursorPos(ref Point lpPoint)
,这是一种外部方法,您可以从“user32.dll”对其进行DllImport。form.Bounds或form.ClientRectangle或form.Location和form.Size或form.Left和form.Top和form.Width和form.Height,所有这些都为您带来了表单边界。在timer_Tick函数事件中,您可以编写以下代码,例如:

var mp = Cursor.Position;
var fb = form.ClientRectangle; // Or form.Bounds

if (mp.X < fb.X || mp.Y < fb.Y || mp.X > fb.X + fb.Width || mp.Y > fb.Y + fb.Height)
{
    // Use GetKeyState from user32.dll to detect if at least 1 key is pressed
    // (look at internet how to do it exactly)
    // If yes MessageBox.Show("Clicked outside");
}
var mp=Cursor.Position;
var fb=form.ClientRectangle;//或者形式界限
如果(mp.Xfb.X+fb.Width | mp.Y>fb.Y+fb.Height)
{
//使用user32.dll中的GetKeyState检测是否至少按下了一个键
//(看看互联网如何做到这一点)
//如果是MessageBox.Show(“单击外部”);
}
如果至少按了一个键,然后使用
MessageBox
显示消息。你可以在互联网上读到如何做我之前谈论过的所有这些事情,如果你成功了,它会起作用的

试试这个:

// Form1.cs

private Point pos1;
private Point pos2;

private bool b = true;
private double diffx;
private double diffy;
private double area;

private void Form1_Deactivate(object sender, EventArgs e)
{
    if (b) (pos1, b) = (Cursor.Position, false);
    else
    { 
        pos2 = Cursor.Position;

        if (pos1.x >= pos2.x) diffx = pos1.x - pos2.x;
        else diffx = pos2.x - pos1.x;

        if (pos1.y >= pos2.y) diffy = pos1.y - pos2.y;
        else diffy = pos2.y - pos1.y;

        area = diffx * diffy;

        MessageBox.Show(area.ToString());
    }
}

但是,在开始点单击程序外部后,您必须再次单击程序,然后在结束点单击程序外部以使程序工作。

没有回答如何获取单击坐标。您能给变量命名一个比
b
更好的名称吗?天哪,我不知道它是干什么的exactly@AustinWBryan哦,天哪,我的代码太糟糕了,哈哈。我是5年前写的,说实话,这太糟糕了。我真的不记得它是如何工作的,但我认为b是一个布尔值,用于保存程序是否已经获得pos1的光标位置。这当然可以更改为将pos1初始化为负的x和y值,然后在if语句中检查pos1是否为负,最后在else分支的末尾再次将pos1赋值为负的x和y值。我会尽快修改答案。顺便说一句,谢谢你试图使我的可怕的代码更好。