问题描述
我有一个winform应用程序(.NET C#)。 从此应用程序,我开始了另一个过程(notepad.exe),并将其停靠在我的窗口中-类似于此处的操作:Docking Window inside another Window。
现在我的问题是,如何捕捉/处理在此停靠的应用程序上发生的鼠标事件? 我尝试过的:
对于上下文,我要实现的目标是在鼠标旁边有一个恒定的工具提示,通知我鼠标相对于面板的位置。参见下面的代码:
ToolTip trackTip;
public Form1
{
trackTip = new ToolTip();
transparentPanel1.MouseMove += new MouseEventHandler((object s,System.Windows.Forms.MouseEventArgs e) => trackTip.Hide(this));
transparentPanel1.MouseLeave += new EventHandler(TransparentPanel1_MouseLeave);
}
void TransparentPanel1_MouseMove(object sender,System.Windows.Forms.MouseEventArgs e)
{
String tipText = String.Format("({0},{1})",e.X,e.Y);
trackTip.Show(tipText,this,e.Location);
}
我找到了viable solution,但是我非常想避免向过程中注入代码,并且我觉得似乎必须为我的特定问题提供更好的解决方案。
如果您能给我提供任何指导,我将不胜感激。我是.NET编程的新手。
解决方法
作为参考,我在这里将两个答案组合在一起:
使用鼠标的全局位置和窗口的位置,我们可以计算鼠标的相对位置。这里有一些示例代码,它们具有真正的基本边界处理,并且对于句柄被关闭等没有真正的错误处理。但是应该让您入门。
首先,基本上是上述答案的副本,其中引入了Windows API以获取窗口和鼠标的位置:
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public static implicit operator Point(POINT point)
{
return new Point(point.X,point.Y);
}
}
[DllImport("user32.dll")]
public static extern bool GetCursorPos(out POINT lpPoint);
public static Point GetCursorPosition()
{
POINT lpPoint;
GetCursorPos(out lpPoint);
return lpPoint;
}
[DllImport("user32.dll",CharSet = CharSet.Auto)]
public static extern IntPtr FindWindow(string strClassName,string strWindowName);
[DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hwnd,ref Rect rectangle);
public struct Rect
{
public int Left { get; set; }
public int Top { get; set; }
public int Right { get; set; }
public int Bottom { get; set; }
}
然后在两者之间进行一些数学运算:
public Point GetRelativeMousePosition(IntPtr windowPtr)
{
Rect windowPostion = new Rect();
GetWindowRect(windowPtr,ref windowPostion);
var mousePosition = GetCursorPosition();
var result = new Point();
result.X = mousePosition.X - windowPostion.Left;
result.Y = mousePosition.Y - windowPostion.Top;
// set some boundaries so we can't go outside.
if (result.X < 0)
result.X = 0;
var maxWidth = windowPostion.Right - windowPostion.Left;
if (result.X > maxWidth)
result.X = maxWidth;
if (result.Y < 0)
result.Y = 0;
var maxHeight = windowPostion.Bottom - windowPostion.Top;
if (result.Y > maxHeight)
result.Y = maxHeight;
return result;
}
然后将它们放在一起:
private void Sample()
{
Process[] processes = Process.GetProcessesByName("notepad");
Process lol = processes[0];
var ptr = lol.MainWindowHandle; // getting this reference is expensive. Better to store and reuse if possible.
var relativePoint = GetRelativeMousePosition(ptr);
Console.WriteLine($"relative mouse x:{relativePoint.X} y:{relativePoint.Y}");
}