diff --git a/Greenshot/Controls/Pipette.cs b/Greenshot/Controls/Pipette.cs
index dbcffaaa8..74a8ea6b8 100644
--- a/Greenshot/Controls/Pipette.cs
+++ b/Greenshot/Controls/Pipette.cs
@@ -56,18 +56,16 @@ namespace Greenshot.Controls {
/// Hotspot Y coordinate
/// Cursor
private static Cursor CreateCursor(Bitmap bitmap, int hotspotX, int hotspotY) {
- IntPtr iconHandle = bitmap.GetHicon();
- IntPtr icon;
- IconInfo iconInfo = new IconInfo();
- User32.GetIconInfo(iconHandle, out iconInfo);
- iconInfo.xHotspot = hotspotX;
- iconInfo.yHotspot = hotspotY;
- iconInfo.fIcon = false;
- icon = User32.CreateIconIndirect(ref iconInfo);
- Cursor returnCursor = new Cursor(icon);
- //User32.DestroyIcon(icon);
- User32.DestroyIcon(iconHandle);
- return returnCursor;
+ using (SafeIconHandle iconHandle = new SafeIconHandle( bitmap.GetHicon())) {
+ IntPtr icon;
+ IconInfo iconInfo = new IconInfo();
+ User32.GetIconInfo(iconHandle, out iconInfo);
+ iconInfo.xHotspot = hotspotX;
+ iconInfo.yHotspot = hotspotY;
+ iconInfo.fIcon = false;
+ icon = User32.CreateIconIndirect(ref iconInfo);
+ return new Cursor(icon);
+ }
}
///
diff --git a/GreenshotPlugin/Core/WindowCapture.cs b/GreenshotPlugin/Core/WindowCapture.cs
index e94adad8b..861e335e5 100644
--- a/GreenshotPlugin/Core/WindowCapture.cs
+++ b/GreenshotPlugin/Core/WindowCapture.cs
@@ -498,33 +498,32 @@ namespace GreenshotPlugin.Core {
capture = new Capture();
}
int x,y;
- IntPtr hicon;
CursorInfo cursorInfo = new CursorInfo();
IconInfo iconInfo;
cursorInfo.cbSize = Marshal.SizeOf(cursorInfo);
if (User32.GetCursorInfo(out cursorInfo)) {
if (cursorInfo.flags == User32.CURSOR_SHOWING) {
- hicon = User32.CopyIcon(cursorInfo.hCursor);
- if (User32.GetIconInfo(hicon, out iconInfo)) {
- Point cursorLocation = GetCursorLocation();
- // Allign cursor location to Bitmap coordinates (instead of Screen coordinates)
- x = cursorLocation.X - iconInfo.xHotspot - capture.ScreenBounds.X;
- y = cursorLocation.Y - iconInfo.yHotspot - capture.ScreenBounds.Y;
- // Set the location
- capture.CursorLocation = new Point(x, y);
-
- using (Icon icon = Icon.FromHandle(hicon)) {
- capture.Cursor = icon;
- }
-
- if (iconInfo.hbmMask != IntPtr.Zero) {
- GDI32.DeleteObject(iconInfo.hbmMask);
- }
- if (iconInfo.hbmColor != IntPtr.Zero) {
- GDI32.DeleteObject(iconInfo.hbmColor);
+ using (SafeIconHandle safeIcon = User32.CopyIcon(cursorInfo.hCursor)) {
+ if (User32.GetIconInfo(safeIcon, out iconInfo)) {
+ Point cursorLocation = GetCursorLocation();
+ // Allign cursor location to Bitmap coordinates (instead of Screen coordinates)
+ x = cursorLocation.X - iconInfo.xHotspot - capture.ScreenBounds.X;
+ y = cursorLocation.Y - iconInfo.yHotspot - capture.ScreenBounds.Y;
+ // Set the location
+ capture.CursorLocation = new Point(x, y);
+
+ using (Icon icon = Icon.FromHandle(safeIcon.DangerousGetHandle())) {
+ capture.Cursor = icon;
+ }
+
+ if (iconInfo.hbmMask != IntPtr.Zero) {
+ GDI32.DeleteObject(iconInfo.hbmMask);
+ }
+ if (iconInfo.hbmColor != IntPtr.Zero) {
+ GDI32.DeleteObject(iconInfo.hbmColor);
+ }
}
}
- User32.DestroyIcon(hicon);
}
}
return capture;
diff --git a/GreenshotPlugin/Core/WindowsHelper.cs b/GreenshotPlugin/Core/WindowsHelper.cs
index 9de12b729..bd9c79562 100644
--- a/GreenshotPlugin/Core/WindowsHelper.cs
+++ b/GreenshotPlugin/Core/WindowsHelper.cs
@@ -627,7 +627,11 @@ namespace GreenshotPlugin.Core {
return User32.IsIconic(this.hWnd) || Location.X <= -32000;
}
set {
- User32.SendMessage(this.hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_MINIMIZE, IntPtr.Zero);
+ if (value) {
+ User32.SendMessage(this.hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_MINIMIZE, IntPtr.Zero);
+ } else {
+ User32.SendMessage(this.hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_RESTORE, IntPtr.Zero);
+ }
}
}
@@ -660,7 +664,7 @@ namespace GreenshotPlugin.Core {
if (monitor != IntPtr.Zero) {
if (appVisibility != null) {
MONITOR_APP_VISIBILITY monitorAppVisibility = appVisibility.GetAppVisibilityOnMonitor(monitor);
- LOG.DebugFormat("App visible: {0}", monitorAppVisibility);
+ LOG.DebugFormat("App {0} visible: {1} on {2}", Text, monitorAppVisibility, screen.Bounds);
if (monitorAppVisibility == MONITOR_APP_VISIBILITY.MAV_APP_VISIBLE) {
return true;
}
@@ -1097,6 +1101,7 @@ namespace GreenshotPlugin.Core {
/// Bitmap with transparency
private Bitmap ApplyTransparency(Bitmap blackBitmap, Bitmap whiteBitmap) {
Bitmap returnBitmap = new Bitmap(blackBitmap.Width, blackBitmap.Height, PixelFormat.Format32bppArgb);
+ returnBitmap.SetResolution(blackBitmap.HorizontalResolution, blackBitmap.VerticalResolution);
using (BitmapBuffer blackBuffer = new BitmapBuffer(blackBitmap, false)) {
blackBuffer.Lock();
using (BitmapBuffer whiteBuffer = new BitmapBuffer(whiteBitmap, false)) {
diff --git a/GreenshotPlugin/UnmanagedHelpers/GDI32.cs b/GreenshotPlugin/UnmanagedHelpers/GDI32.cs
index 56c8d4205..583ea4ff3 100644
--- a/GreenshotPlugin/UnmanagedHelpers/GDI32.cs
+++ b/GreenshotPlugin/UnmanagedHelpers/GDI32.cs
@@ -21,6 +21,8 @@
using System;
using System.Drawing;
using System.Runtime.InteropServices;
+using System.Security;
+using Microsoft.Win32.SafeHandles;
namespace GreenshotPlugin.UnmanagedHelpers {
public static class GDIExtensions {
@@ -37,6 +39,25 @@ namespace GreenshotPlugin.UnmanagedHelpers {
return topLeftVisible && topRightVisible && bottomLeftVisible && bottomRightVisible;
}
}
+
+ ///
+ /// A hbitmap SafeHandle implementation
+ ///
+ public class SafeHBitmapHandle : SafeHandleZeroOrMinusOneIsInvalid {
+ [SecurityCritical]
+ private SafeHBitmapHandle(): base(true) {
+ }
+
+ [SecurityCritical]
+ public SafeHBitmapHandle(IntPtr preexistingHandle) : base(true) {
+ SetHandle(preexistingHandle);
+ }
+
+ protected override bool ReleaseHandle() {
+ return GDI32.DeleteObject(handle);
+ }
+ }
+
///
/// GDI32 Helpers
///
@@ -77,9 +98,11 @@ namespace GreenshotPlugin.UnmanagedHelpers {
try {
hDCDest = target.GetHdc();
hDCSrc = CreateCompatibleDC(hDCDest);
- IntPtr pOrig = SelectObject(hDCSrc, sourceBitmap.GetHbitmap());
- StretchBlt(hDCDest, destination.X, destination.Y, destination.Width, destination.Height, hDCSrc, source.Left, source.Top, source.Width, source.Height, CopyPixelOperation.SourceCopy);
- IntPtr pNew = SelectObject(hDCDest, pOrig);
+ using (SafeHBitmapHandle hBitmapHandle = new SafeHBitmapHandle(sourceBitmap.GetHbitmap())) {
+ IntPtr pOrig = SelectObject(hDCSrc, hBitmapHandle.DangerousGetHandle());
+ StretchBlt(hDCDest, destination.X, destination.Y, destination.Width, destination.Height, hDCSrc, source.Left, source.Top, source.Width, source.Height, CopyPixelOperation.SourceCopy);
+ IntPtr pNew = SelectObject(hDCDest, pOrig);
+ }
} finally {
if (hDCSrc != IntPtr.Zero) {
DeleteDC(hDCSrc);
@@ -101,9 +124,11 @@ namespace GreenshotPlugin.UnmanagedHelpers {
try {
hDCDest = target.GetHdc();
hDCSrc = CreateCompatibleDC(hDCDest);
- IntPtr pOrig = SelectObject(hDCSrc, sourceBitmap.GetHbitmap());
- BitBlt(hDCDest, destination.X, destination.Y, source.Width, source.Height, hDCSrc, source.Left, source.Top, CopyPixelOperation.SourceCopy);
- IntPtr pNew = SelectObject(hDCDest, pOrig);
+ using (SafeHBitmapHandle hBitmapHandle = new SafeHBitmapHandle(sourceBitmap.GetHbitmap())) {
+ IntPtr pOrig = SelectObject(hDCSrc, hBitmapHandle.DangerousGetHandle());
+ BitBlt(hDCDest, destination.X, destination.Y, source.Width, source.Height, hDCSrc, source.Left, source.Top, CopyPixelOperation.SourceCopy);
+ IntPtr pNew = SelectObject(hDCDest, pOrig);
+ }
} finally {
if (hDCSrc != IntPtr.Zero) {
DeleteDC(hDCSrc);
diff --git a/GreenshotPlugin/UnmanagedHelpers/User32.cs b/GreenshotPlugin/UnmanagedHelpers/User32.cs
index 9279abff1..729aff5fe 100644
--- a/GreenshotPlugin/UnmanagedHelpers/User32.cs
+++ b/GreenshotPlugin/UnmanagedHelpers/User32.cs
@@ -25,6 +25,8 @@ using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
+using Microsoft.Win32.SafeHandles;
+
namespace GreenshotPlugin.UnmanagedHelpers {
///
/// Used with EnumWindows or EnumChildWindows
@@ -45,6 +47,22 @@ namespace GreenshotPlugin.UnmanagedHelpers {
///
///
public delegate void WinEventDelegate(IntPtr hWinEventHook, WinEvent eventType, IntPtr hwnd, EventObjects idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
+
+ ///
+ /// A SafeHandle class implementation for the hIcon
+ ///
+ public class SafeIconHandle : SafeHandleZeroOrMinusOneIsInvalid {
+ private SafeIconHandle(): base(true) {
+ }
+
+ public SafeIconHandle(IntPtr hIcon) : base(true) {
+ this.SetHandle(hIcon);
+ }
+
+ protected override bool ReleaseHandle() {
+ return User32.DestroyIcon(this.handle);
+ }
+ }
///
/// User32 Wrappers
@@ -210,13 +228,13 @@ namespace GreenshotPlugin.UnmanagedHelpers {
///
///
[DllImport("user32", SetLastError = true)]
- public static extern IntPtr CopyIcon(IntPtr hIcon);
+ public static extern SafeIconHandle CopyIcon(IntPtr hIcon);
[DllImport("user32", SetLastError = true)]
public static extern bool DestroyIcon(IntPtr hIcon);
[DllImport("user32", SetLastError = true)]
public static extern bool GetCursorInfo(out CursorInfo cursorInfo);
[DllImport("user32", SetLastError = true)]
- public static extern bool GetIconInfo(IntPtr hIcon, out IconInfo iconInfo);
+ public static extern bool GetIconInfo(SafeIconHandle iconHandle, out IconInfo iconInfo);
[DllImport("user32", SetLastError = true)]
public static extern bool DrawIcon(IntPtr hDC, int X, int Y, IntPtr hIcon);
[DllImport("user32", SetLastError = true)]