OnTopReplica/src/OnTopReplica/Win32Helper.cs
Lorenz Cuno Klopfenstein a7774b6677 Code re-org
2018-04-10 18:52:40 +02:00

127 lines
5.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using OnTopReplica.Native;
using System.Drawing;
using System.Windows.Forms;
namespace OnTopReplica {
public static class Win32Helper {
#region Injection
/// <summary>Inject a fake left mouse click on a target window, on a location expressed in client coordinates.</summary>
/// <param name="window">Target window to click on.</param>
/// <param name="clickLocation">Location of the mouse click expressed in client coordiantes of the target window.</param>
/// <param name="doubleClick">True if a double click should be injected.</param>
public static void InjectFakeMouseClick(IntPtr window, CloneClickEventArgs clickArgs) {
NPoint clientClickLocation = NPoint.FromPoint(clickArgs.ClientClickLocation);
NPoint scrClickLocation = WindowManagerMethods.ClientToScreen(window, clientClickLocation);
//HACK (?)
//If target window has a Menu (which appears on the thumbnail) move the clicked location down
//in order to adjust (the menu isn't part of the window's client rect).
IntPtr hMenu = WindowMethods.GetMenu(window);
if (hMenu != IntPtr.Zero)
scrClickLocation.Y -= SystemInformation.MenuHeight;
IntPtr hChild = GetRealChildControlFromPoint(window, scrClickLocation);
NPoint clntClickLocation = WindowManagerMethods.ScreenToClient(hChild, scrClickLocation);
if (clickArgs.Buttons == MouseButtons.Left) {
if(clickArgs.IsDoubleClick)
InjectDoubleLeftMouseClick(hChild, clntClickLocation);
else
InjectLeftMouseClick(hChild, clntClickLocation);
}
else if (clickArgs.Buttons == MouseButtons.Right) {
if(clickArgs.IsDoubleClick)
InjectDoubleRightMouseClick(hChild, clntClickLocation);
else
InjectRightMouseClick(hChild, clntClickLocation);
}
}
private static void InjectLeftMouseClick(IntPtr child, NPoint clientLocation) {
IntPtr lParamClickLocation = MessagingMethods.MakeLParam(clientLocation.X, clientLocation.Y);
MessagingMethods.PostMessage(child, WM.LBUTTONDOWN, new IntPtr(MK.LBUTTON), lParamClickLocation);
MessagingMethods.PostMessage(child, WM.LBUTTONUP, new IntPtr(MK.LBUTTON), lParamClickLocation);
#if DEBUG
System.Diagnostics.Debug.WriteLine("Left click on window #" + child.ToString() + " at " + clientLocation.ToString());
#endif
}
private static void InjectRightMouseClick(IntPtr child, NPoint clientLocation) {
IntPtr lParamClickLocation = MessagingMethods.MakeLParam(clientLocation.X, clientLocation.Y);
MessagingMethods.PostMessage(child, WM.RBUTTONDOWN, new IntPtr(MK.RBUTTON), lParamClickLocation);
MessagingMethods.PostMessage(child, WM.RBUTTONUP, new IntPtr(MK.RBUTTON), lParamClickLocation);
#if DEBUG
System.Diagnostics.Debug.WriteLine("Right click on window #" + child.ToString() + " at " + clientLocation.ToString());
#endif
}
private static void InjectDoubleLeftMouseClick(IntPtr child, NPoint clientLocation) {
IntPtr lParamClickLocation = MessagingMethods.MakeLParam(clientLocation.X, clientLocation.Y);
MessagingMethods.PostMessage(child, WM.LBUTTONDBLCLK, new IntPtr(MK.LBUTTON), lParamClickLocation);
#if DEBUG
System.Diagnostics.Debug.WriteLine("Double left click on window #" + child.ToString() + " at " + clientLocation.ToString());
#endif
}
private static void InjectDoubleRightMouseClick(IntPtr child, NPoint clientLocation) {
IntPtr lParamClickLocation = MessagingMethods.MakeLParam(clientLocation.X, clientLocation.Y);
MessagingMethods.PostMessage(child, WM.RBUTTONDBLCLK, new IntPtr(MK.RBUTTON), lParamClickLocation);
#if DEBUG
System.Diagnostics.Debug.WriteLine("Double right click on window #" + child.ToString() + " at " + clientLocation.ToString());
#endif
}
#endregion
/// <summary>Returns the child control of a window corresponding to a screen location.</summary>
/// <param name="parent">Parent window to explore.</param>
/// <param name="scrClickLocation">Child control location in screen coordinates.</param>
private static IntPtr GetRealChildControlFromPoint(IntPtr parent, NPoint scrClickLocation) {
IntPtr curr = parent, child = IntPtr.Zero;
do {
child = WindowManagerMethods.RealChildWindowFromPoint(curr,
WindowManagerMethods.ScreenToClient(curr, scrClickLocation));
if (child == IntPtr.Zero || child == curr)
break;
//Update for next loop
curr = child;
}
while (true);
//Safety check, shouldn't happen
if (curr == IntPtr.Zero)
curr = parent;
return curr;
}
/// <summary>
/// Gets a handle to the window that currently is in the foreground.
/// </summary>
/// <returns>May return null if call fails or no valid window selected.</returns>
public static WindowHandle GetCurrentForegroundWindow() {
IntPtr handle = WindowManagerMethods.GetForegroundWindow();
if (handle == IntPtr.Zero)
return null;
return new WindowHandle(handle);
}
}
}