C# - 停靠外部应用程序 - 鼠标事件
C# - Docked External application - Mouse events
我有一个 winform 应用程序 (.NET C#)。
我从这个应用程序启动了另一个进程 (notepad.exe) 并将其停靠到我的 window - 类似于此处的操作方式:Docking Window inside another Window.
现在我的问题是,如何 catch/handle 在此停靠应用程序上进行鼠标事件?
我尝试过的:
- 在对接面板上创建一个透明面板。当我无法“通过”不可见面板单击(或执行任何其他操作)时出现问题
- 全局鼠标钩子。我不喜欢这个解决方案,因为我只对表单中的鼠标位置感兴趣。另外,我需要相对于 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 编程新手。
为了参考,我在这里将两个答案合并为一个:
Getting mouse position in c#
How to get window's position?
利用鼠标的全局位置和window的位置我们可以计算出鼠标的相对位置。下面是一些示例代码,其中包含真正基本的边界处理,并且没有针对句柄关闭等的真正错误处理。但应该可以帮助您入门。
首先,基本上是上述答案的副本,引入 windows API 来获取 window 和鼠标位置:
[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}");
}
我有一个 winform 应用程序 (.NET C#)。 我从这个应用程序启动了另一个进程 (notepad.exe) 并将其停靠到我的 window - 类似于此处的操作方式:Docking Window inside another Window.
现在我的问题是,如何 catch/handle 在此停靠应用程序上进行鼠标事件? 我尝试过的:
- 在对接面板上创建一个透明面板。当我无法“通过”不可见面板单击(或执行任何其他操作)时出现问题
- 全局鼠标钩子。我不喜欢这个解决方案,因为我只对表单中的鼠标位置感兴趣。另外,我需要相对于 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 编程新手。
为了参考,我在这里将两个答案合并为一个:
Getting mouse position in c#
How to get window's position?
利用鼠标的全局位置和window的位置我们可以计算出鼠标的相对位置。下面是一些示例代码,其中包含真正基本的边界处理,并且没有针对句柄关闭等的真正错误处理。但应该可以帮助您入门。
首先,基本上是上述答案的副本,引入 windows API 来获取 window 和鼠标位置:
[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}");
}