Tried to use Greenshot from Wine, and found that the user32.dll GetPhysicalCursorPos entry point is not supported, although I don't know if this is just the tip of the iceberg I though I would see what happens if we just ignore that call if an exception occurs. [skip ci]

This commit is contained in:
RKrom 2014-11-04 11:26:15 +01:00
commit eefdf2b2eb
2 changed files with 33 additions and 21 deletions

View file

@ -458,30 +458,13 @@ namespace GreenshotPlugin.Core {
return new Rectangle(left, top, (right + Math.Abs(left)), (bottom + Math.Abs(top))); return new Rectangle(left, top, (right + Math.Abs(left)), (bottom + Math.Abs(top)));
} }
/// <summary>
/// Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7.
/// <returns>Point with cursor location, relative to the origin of the monitor setup (i.e. negative coordinates are
/// possible in multiscreen setups)</returns>
public static Point GetCursorLocation() {
if (Environment.OSVersion.Version.Major >= 6) {
POINT cursorLocation;
if (User32.GetPhysicalCursorPos(out cursorLocation)) {
return new Point(cursorLocation.X, cursorLocation.Y);
} else {
Win32Error error = Win32.GetLastErrorCode();
LOG.ErrorFormat("Error retrieving PhysicalCursorPos : {0}", Win32.GetMessage(error));
}
}
return new Point(Cursor.Position.X, Cursor.Position.Y);
}
/// <summary> /// <summary>
/// Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7. This implementation /// Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7. This implementation
/// can conveniently be used when the cursor location is needed to deal with a fullscreen bitmap. /// can conveniently be used when the cursor location is needed to deal with a fullscreen bitmap.
/// <returns>Point with cursor location, relative to the top left corner of the monitor setup (which itself might /// <returns>Point with cursor location, relative to the top left corner of the monitor setup (which itself might
/// actually not be on any screen)</returns> /// actually not be on any screen)</returns>
public static Point GetCursorLocationRelativeToScreenBounds() { public static Point GetCursorLocationRelativeToScreenBounds() {
return GetLocationRelativeToScreenBounds(GetCursorLocation()); return GetLocationRelativeToScreenBounds(User32.GetCursorLocation());
} }
/// <summary> /// <summary>
@ -515,7 +498,7 @@ namespace GreenshotPlugin.Core {
if (cursorInfo.flags == User32.CURSOR_SHOWING) { if (cursorInfo.flags == User32.CURSOR_SHOWING) {
using (SafeIconHandle safeIcon = User32.CopyIcon(cursorInfo.hCursor)) { using (SafeIconHandle safeIcon = User32.CopyIcon(cursorInfo.hCursor)) {
if (User32.GetIconInfo(safeIcon, out iconInfo)) { if (User32.GetIconInfo(safeIcon, out iconInfo)) {
Point cursorLocation = GetCursorLocation(); Point cursorLocation = User32.GetCursorLocation();
// Allign cursor location to Bitmap coordinates (instead of Screen coordinates) // Allign cursor location to Bitmap coordinates (instead of Screen coordinates)
x = cursorLocation.X - iconInfo.xHotspot - capture.ScreenBounds.X; x = cursorLocation.X - iconInfo.xHotspot - capture.ScreenBounds.X;
y = cursorLocation.Y - iconInfo.yHotspot - capture.ScreenBounds.Y; y = cursorLocation.Y - iconInfo.yHotspot - capture.ScreenBounds.Y;

View file

@ -18,6 +18,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
@ -28,6 +29,7 @@ using System.Windows.Forms;
using Microsoft.Win32.SafeHandles; using Microsoft.Win32.SafeHandles;
using System.Security; using System.Security;
using System.Security.Permissions; using System.Security.Permissions;
using log4net;
namespace GreenshotPlugin.UnmanagedHelpers { namespace GreenshotPlugin.UnmanagedHelpers {
/// <summary> /// <summary>
@ -42,6 +44,8 @@ namespace GreenshotPlugin.UnmanagedHelpers {
/// User32 Wrappers /// User32 Wrappers
/// </summary> /// </summary>
public static class User32 { public static class User32 {
private static readonly ILog LOG = LogManager.GetLogger(typeof(User32));
private static bool _CanCallGetPhysicalCursorPos = true;
public const int SC_RESTORE = 0xF120; public const int SC_RESTORE = 0xF120;
public const int SC_CLOSE = 0xF060; public const int SC_CLOSE = 0xF060;
public const int SC_MAXIMIZE = 0xF030; public const int SC_MAXIMIZE = 0xF030;
@ -55,7 +59,8 @@ namespace GreenshotPlugin.UnmanagedHelpers {
public const int MONITOR_DEFAULTTOPRIMARY = 1; public const int MONITOR_DEFAULTTOPRIMARY = 1;
public const int MONITOR_DEFAULTTONEAREST = 2; public const int MONITOR_DEFAULTTONEAREST = 2;
public const Int32 CURSOR_SHOWING = 0x00000001; public const Int32 CURSOR_SHOWING = 0x00000001;
#region DllImports
[DllImport("user32", SetLastError = true)] [DllImport("user32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
public extern static bool IsWindowVisible(IntPtr hWnd); public extern static bool IsWindowVisible(IntPtr hWnd);
@ -186,7 +191,7 @@ namespace GreenshotPlugin.UnmanagedHelpers {
[DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)] [DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam, SendMessageTimeoutFlags fuFlags, uint uTimeout, out UIntPtr lpdwResult); public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam, SendMessageTimeoutFlags fuFlags, uint uTimeout, out UIntPtr lpdwResult);
[DllImport("user32", SetLastError = true)] [DllImport("user32", SetLastError = true)]
public static extern bool GetPhysicalCursorPos(out POINT cursorLocation); private static extern bool GetPhysicalCursorPos(out POINT cursorLocation);
[DllImport("user32", SetLastError=true)] [DllImport("user32", SetLastError=true)]
public static extern int MapWindowPoints(IntPtr hwndFrom, IntPtr hwndTo, ref POINT lpPoints, [MarshalAs(UnmanagedType.U4)] int cPoints); public static extern int MapWindowPoints(IntPtr hwndFrom, IntPtr hwndTo, ref POINT lpPoints, [MarshalAs(UnmanagedType.U4)] int cPoints);
[DllImport("user32", SetLastError = true)] [DllImport("user32", SetLastError = true)]
@ -213,6 +218,30 @@ namespace GreenshotPlugin.UnmanagedHelpers {
[DllImport("user32", SetLastError = true)] [DllImport("user32", SetLastError = true)]
public static extern IntPtr CreateIconIndirect(ref IconInfo icon); public static extern IntPtr CreateIconIndirect(ref IconInfo icon);
#endregion
/// <summary>
/// Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7.
/// <returns>Point with cursor location, relative to the origin of the monitor setup
/// (i.e. negative coordinates arepossible in multiscreen setups)</returns>
public static Point GetCursorLocation() {
if (Environment.OSVersion.Version.Major >= 6 && _CanCallGetPhysicalCursorPos) {
POINT cursorLocation;
try {
if (GetPhysicalCursorPos(out cursorLocation)) {
return new Point(cursorLocation.X, cursorLocation.Y);
} else {
Win32Error error = Win32.GetLastErrorCode();
LOG.ErrorFormat("Error retrieving PhysicalCursorPos : {0}", Win32.GetMessage(error));
}
} catch (Exception ex) {
LOG.Error("Exception retrieving PhysicalCursorPos, no longer calling this. Cause :", ex);
_CanCallGetPhysicalCursorPos = false;
}
}
return new Point(Cursor.Position.X, Cursor.Position.Y);
}
/// <summary> /// <summary>
/// Wrapper for the GetClassLong which decides if the system is 64-bit or not and calls the right one. /// Wrapper for the GetClassLong which decides if the system is 64-bit or not and calls the right one.
/// </summary> /// </summary>