Merge remote-tracking branch 'remotes/origin/master' into release/1.2.9

This commit is contained in:
Robin 2016-05-24 13:13:48 +02:00
commit 0323705513
276 changed files with 5382 additions and 3666 deletions

View file

@ -26,6 +26,7 @@ using GreenshotPlugin.UnmanagedHelpers;
using log4net;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
@ -34,12 +35,6 @@ using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
/// <summary>
/// Code for handling with "windows"
/// Main code is taken from vbAccelerator, location:
/// http://www.vbaccelerator.com/home/NET/Code/Libraries/Windows/Enumerating_Windows/article.asp
/// but a LOT of changes/enhancements were made to adapt it for Greenshot.
/// </summary>
namespace GreenshotPlugin.Core {
#region EnumWindows
/// <summary>
@ -47,7 +42,7 @@ namespace GreenshotPlugin.Core {
/// </summary>
public class WindowsEnumerator {
#region Member Variables
private List<WindowDetails> items = null;
private List<WindowDetails> items;
#endregion
/// <summary>
@ -89,7 +84,7 @@ namespace GreenshotPlugin.Core {
public WindowsEnumerator GetWindows(IntPtr hWndParent, string classname) {
items = new List<WindowDetails>();
List<WindowDetails> windows = new List<WindowDetails>();
User32.EnumChildWindows(hWndParent, new EnumWindowsProc(WindowEnum), IntPtr.Zero);
User32.EnumChildWindows(hWndParent, WindowEnum, IntPtr.Zero);
bool hasParent = !IntPtr.Zero.Equals(hWndParent);
string parentText = null;
@ -139,7 +134,7 @@ namespace GreenshotPlugin.Core {
/// <param name="hWnd">Window handle to add</param>
/// <returns>True to continue enumeration, False to stop</returns>
protected virtual bool OnWindowEnum(IntPtr hWnd) {
if (!WindowDetails.isIgnoreHandle(hWnd)) {
if (!WindowDetails.IsIgnoreHandle(hWnd)) {
items.Add(new WindowDetails(hWnd));
}
return true;
@ -150,25 +145,29 @@ namespace GreenshotPlugin.Core {
// nothing to do
}
#endregion
}
}
#endregion EnumWindows
/// <summary>
#region WindowDetails
/// <summary>
/// Code for handling with "windows"
/// Main code is taken from vbAccelerator, location:
/// http://www.vbaccelerator.com/home/NET/Code/Libraries/Windows/Enumerating_Windows/article.asp
/// but a LOT of changes/enhancements were made to adapt it for Greenshot.
/// <summary>
/// Provides details about a Window returned by the
/// enumeration
/// </summary>
public class WindowDetails : IEquatable<WindowDetails>{
private const string METRO_WINDOWS_CLASS = "Windows.UI.Core.CoreWindow";
private const string METRO_WINDOWS_CLASS = "Windows.UI.Core.CoreWindow"; // Windows 10 uses ApplicationFrameWindow
private const string METRO_APPLAUNCHER_CLASS = "ImmersiveLauncher";
private const string METRO_GUTTER_CLASS = "ImmersiveGutter";
private static ILog LOG = LogManager.GetLogger(typeof(WindowDetails));
private static CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
private static List<IntPtr> ignoreHandles = new List<IntPtr>();
private static List<string> excludeProcessesFromFreeze = new List<string>();
private static IAppVisibility appVisibility = null;
private static readonly ILog LOG = LogManager.GetLogger(typeof(WindowDetails));
private static readonly CoreConfiguration Conf = IniConfig.GetIniSection<CoreConfiguration>();
private static readonly List<IntPtr> IgnoreHandles = new List<IntPtr>();
private static readonly List<string> ExcludeProcessesFromFreeze = new List<string>();
private static readonly IAppVisibility appVisibility;
static WindowDetails() {
try {
@ -180,33 +179,37 @@ namespace GreenshotPlugin.Core {
}
public static void AddProcessToExcludeFromFreeze(string processname) {
if (!excludeProcessesFromFreeze.Contains(processname)) {
excludeProcessesFromFreeze.Add(processname);
if (!ExcludeProcessesFromFreeze.Contains(processname)) {
ExcludeProcessesFromFreeze.Add(processname);
}
}
internal static bool isIgnoreHandle(IntPtr handle) {
return ignoreHandles.Contains(handle);
internal static bool IsIgnoreHandle(IntPtr handle) {
return IgnoreHandles.Contains(handle);
}
private List<WindowDetails> childWindows = null;
private IntPtr parentHandle = IntPtr.Zero;
private WindowDetails parent = null;
private bool frozen = false;
private List<WindowDetails> _childWindows;
private IntPtr _parentHandle = IntPtr.Zero;
private WindowDetails _parent;
private bool _frozen;
public bool isApp {
/// <summary>
/// This checks if the window is a Windows 8 App
/// For Windows 10 most normal code works, as it's hosted inside "ApplicationFrameWindow"
/// </summary>
public bool IsApp {
get {
return METRO_WINDOWS_CLASS.Equals(ClassName);
}
}
public bool isGutter {
public bool IsGutter {
get {
return METRO_GUTTER_CLASS.Equals(ClassName);
}
}
public bool isAppLauncher {
public bool IsAppLauncher {
get {
return METRO_APPLAUNCHER_CLASS.Equals(ClassName);
}
@ -215,16 +218,16 @@ namespace GreenshotPlugin.Core {
/// <summary>
/// Check if this window is the window of a metro app
/// </summary>
public bool isMetroApp {
public bool IsMetroApp {
get {
return isAppLauncher || isApp;
return IsAppLauncher || IsApp;
}
}
/// <summary>
/// The window handle.
/// </summary>
private IntPtr hWnd = IntPtr.Zero;
private readonly IntPtr _hWnd = IntPtr.Zero;
/// <summary>
/// To allow items to be compared, the hash code
@ -257,15 +260,15 @@ namespace GreenshotPlugin.Core {
public bool HasChildren {
get {
return (childWindows != null) && (childWindows.Count > 0);
return (_childWindows != null) && (_childWindows.Count > 0);
}
}
public void FreezeDetails() {
frozen = true;
_frozen = true;
}
public void UnfreezeDetails() {
frozen = false;
_frozen = false;
}
public string ProcessPath {
@ -297,7 +300,7 @@ namespace GreenshotPlugin.Core {
LOG.WarnFormat("Couldn't get icon for window {0} due to: {1}", Text, ex.Message);
LOG.Warn(ex);
}
if (isMetroApp) {
if (IsMetroApp) {
// No method yet to get the metro icon
return null;
}
@ -321,8 +324,8 @@ namespace GreenshotPlugin.Core {
IntPtr ICON_BIG = new IntPtr(1);
IntPtr ICON_SMALL2 = new IntPtr(2);
IntPtr iconHandle = User32.SendMessage(hwnd, (int)WindowsMessages.WM_GETICON, ICON_BIG, IntPtr.Zero);
if (conf.UseLargeIcons) {
IntPtr iconHandle;
if (Conf.UseLargeIcons) {
iconHandle = User32.SendMessage(hwnd, (int)WindowsMessages.WM_GETICON, ICON_BIG, IntPtr.Zero);
if (iconHandle == IntPtr.Zero) {
iconHandle = User32.GetClassLongWrapper(hwnd, (int)ClassLongIndex.GCL_HICON);
@ -357,7 +360,7 @@ namespace GreenshotPlugin.Core {
/// </summary>
/// <param name="ignoreHandle"></param>
public static void RegisterIgnoreHandle(IntPtr ignoreHandle) {
ignoreHandles.Add(ignoreHandle);
IgnoreHandles.Add(ignoreHandle);
}
/// <summary>
@ -365,24 +368,25 @@ namespace GreenshotPlugin.Core {
/// </summary>
/// <param name="ignoreHandle"></param>
public static void UnregisterIgnoreHandle(IntPtr ignoreHandle) {
ignoreHandles.Remove(ignoreHandle);
IgnoreHandles.Remove(ignoreHandle);
}
public List<WindowDetails> Children {
get {
if (childWindows == null) {
if (_childWindows == null) {
GetChildren();
}
return childWindows;
return _childWindows;
}
}
/// <summary>
/// Retrieve all windows with a certain title or classname
/// </summary>
/// <param name="windows"></param>
/// <param name="titlePattern">The regexp to look for in the title</param>
/// <param name="classnamePattern">The regexp to look for in the classname</param>
/// <returns>List<WindowDetails> with all the found windows</returns>
/// <returns>List WindowDetails with all the found windows</returns>
private static List<WindowDetails> FindWindow(List<WindowDetails> windows, string titlePattern, string classnamePattern) {
List<WindowDetails> foundWindows = new List<WindowDetails>();
Regex titleRegexp = null;
@ -430,16 +434,16 @@ namespace GreenshotPlugin.Core {
public IntPtr ParentHandle {
get {
if (parentHandle == IntPtr.Zero) {
parentHandle = User32.GetParent(Handle);
parent = null;
if (_parentHandle == IntPtr.Zero) {
_parentHandle = User32.GetParent(Handle);
_parent = null;
}
return parentHandle;
return _parentHandle;
}
set {
if (parentHandle != value) {
parentHandle = value;
parent = null;
if (_parentHandle != value) {
_parentHandle = value;
_parent = null;
}
}
}
@ -448,15 +452,15 @@ namespace GreenshotPlugin.Core {
/// </summary>
/// <returns>WindowDetails of the parent, or null if none</returns>
public WindowDetails GetParent() {
if (parent == null) {
if (parentHandle == IntPtr.Zero) {
parentHandle = User32.GetParent(Handle);
if (_parent == null) {
if (_parentHandle == IntPtr.Zero) {
_parentHandle = User32.GetParent(Handle);
}
if (parentHandle != IntPtr.Zero) {
parent = new WindowDetails(parentHandle);
if (_parentHandle != IntPtr.Zero) {
_parent = new WindowDetails(_parentHandle);
}
}
return parent;
return _parent;
}
/// <summary>
@ -464,10 +468,10 @@ namespace GreenshotPlugin.Core {
/// One should normally use the getter "Children"
/// </summary>
public List<WindowDetails> GetChildren() {
if (childWindows == null) {
if (_childWindows == null) {
return GetChildren(0);
}
return childWindows;
return _childWindows;
}
/// <summary>
@ -475,16 +479,16 @@ namespace GreenshotPlugin.Core {
/// </summary>
/// <param name="levelsToGo">Specify how many levels we go in</param>
public List<WindowDetails> GetChildren(int levelsToGo) {
if (childWindows == null) {
childWindows = new List<WindowDetails>();
foreach(WindowDetails childWindow in new WindowsEnumerator().GetWindows(hWnd, null).Items) {
childWindows.Add(childWindow);
if (_childWindows == null) {
_childWindows = new List<WindowDetails>();
foreach(WindowDetails childWindow in new WindowsEnumerator().GetWindows(_hWnd, null).Items) {
_childWindows.Add(childWindow);
if (levelsToGo > 0) {
childWindow.GetChildren(levelsToGo-1);
}
}
}
return childWindows;
return _childWindows;
}
/// <summary>
@ -492,7 +496,7 @@ namespace GreenshotPlugin.Core {
/// </summary>
/// <param name="titlePattern">The regexp to look for in the title</param>
/// <param name="classnamePattern">The regexp to look for in the classname</param>
/// <returns>List<WindowDetails> with all the found windows, or an empty list</returns>
/// <returns>List WindowDetails with all the found windows, or an empty list</returns>
public List<WindowDetails> FindChildren(string titlePattern, string classnamePattern) {
return FindWindow(Children, titlePattern, classnamePattern);
}
@ -500,7 +504,7 @@ namespace GreenshotPlugin.Core {
/// <summary>
/// Recursing helper method for the FindPath
/// </summary>
/// <param name="classnames">List<string> with classnames</param>
/// <param name="classnames">List string with classnames</param>
/// <param name="index">The index in the list to look for</param>
/// <returns>WindowDetails if a match was found</returns>
private WindowDetails FindPath(List<string> classnames, int index) {
@ -542,6 +546,7 @@ namespace GreenshotPlugin.Core {
/// <summary>
/// Deep scan for a certain classname pattern
/// </summary>
/// <param name="windowDetails">Window to scan into</param>
/// <param name="classnamePattern">Classname regexp pattern</param>
/// <returns>The first WindowDetails found</returns>
public static WindowDetails DeepScan(WindowDetails windowDetails, Regex classnamePattern) {
@ -575,7 +580,7 @@ namespace GreenshotPlugin.Core {
return null;
}
WindowDetails windowDetails = new WindowDetails(tmphWnd);
windowDetails.parent = this;
windowDetails._parent = this;
return windowDetails;
}
@ -584,38 +589,38 @@ namespace GreenshotPlugin.Core {
/// </summary>
public IntPtr Handle {
get {
return hWnd;
return _hWnd;
}
}
private string text = null;
private string _text;
/// <summary>
/// Gets the window's title (caption)
/// </summary>
public string Text {
set {
text = value;
_text = value;
}
get {
if (text == null) {
if (_text == null) {
StringBuilder title = new StringBuilder(260, 260);
User32.GetWindowText(hWnd, title, title.Capacity);
text = title.ToString();
User32.GetWindowText(_hWnd, title, title.Capacity);
_text = title.ToString();
}
return text;
return _text;
}
}
private string className = null;
private string _className;
/// <summary>
/// Gets the window's class name.
/// </summary>
public string ClassName {
get {
if (className == null) {
className = GetClassName(hWnd);
if (_className == null) {
_className = GetClassName(_hWnd);
}
return className;
return _className;
}
}
@ -624,16 +629,16 @@ namespace GreenshotPlugin.Core {
/// </summary>
public bool Iconic {
get {
if (isMetroApp) {
if (IsMetroApp) {
return !Visible;
}
return User32.IsIconic(hWnd) || Location.X <= -32000;
return User32.IsIconic(_hWnd) || Location.X <= -32000;
}
set {
if (value) {
User32.SendMessage(hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_MINIMIZE, IntPtr.Zero);
User32.SendMessage(_hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_MINIMIZE, IntPtr.Zero);
} else {
User32.SendMessage(hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_RESTORE, IntPtr.Zero);
User32.SendMessage(_hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_RESTORE, IntPtr.Zero);
}
}
}
@ -643,7 +648,8 @@ namespace GreenshotPlugin.Core {
/// </summary>
public bool Maximised {
get {
if (isApp) {
if (IsApp)
{
if (Visible) {
Rectangle windowRectangle = WindowRectangle;
foreach (Screen screen in Screen.AllScreens) {
@ -656,13 +662,13 @@ namespace GreenshotPlugin.Core {
}
return false;
}
return User32.IsZoomed(hWnd);
return User32.IsZoomed(_hWnd);
}
set {
if (value) {
User32.SendMessage(hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_MAXIMIZE, IntPtr.Zero);
User32.SendMessage(_hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_MAXIMIZE, IntPtr.Zero);
} else {
User32.SendMessage(hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_MINIMIZE, IntPtr.Zero);
User32.SendMessage(_hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_MINIMIZE, IntPtr.Zero);
}
}
}
@ -679,7 +685,7 @@ namespace GreenshotPlugin.Core {
/// </summary>
public bool Visible {
get {
if (isApp) {
if (IsApp) {
Rectangle windowRectangle = WindowRectangle;
foreach (Screen screen in Screen.AllScreens) {
if (screen.Bounds.Contains(windowRectangle)) {
@ -705,21 +711,21 @@ namespace GreenshotPlugin.Core {
}
return false;
}
if (isGutter) {
if (IsGutter) {
// gutter is only made available when it's visible
return true;
}
if (isAppLauncher) {
if (IsAppLauncher) {
return IsAppLauncherVisible;
}
return User32.IsWindowVisible(hWnd);
return User32.IsWindowVisible(_hWnd);
}
}
public bool HasParent {
get {
GetParent();
return parentHandle != IntPtr.Zero;
return _parentHandle != IntPtr.Zero;
}
}
@ -751,12 +757,13 @@ namespace GreenshotPlugin.Core {
/// Make sure the next call of a cached value is guaranteed the real value
/// </summary>
public void Reset() {
previousWindowRectangle = Rectangle.Empty;
_previousWindowRectangle = Rectangle.Empty;
}
private Rectangle previousWindowRectangle = Rectangle.Empty;
private long lastWindowRectangleRetrieveTime = 0;
private const long CACHE_TIME = TimeSpan.TicksPerSecond * 2;
private Rectangle _previousWindowRectangle = Rectangle.Empty;
private long _lastWindowRectangleRetrieveTime;
private const long CacheTime = TimeSpan.TicksPerSecond * 2;
/// <summary>
/// Gets the bounding rectangle of the window
/// </summary>
@ -764,33 +771,59 @@ namespace GreenshotPlugin.Core {
get {
// Try to return a cached value
long now = DateTime.Now.Ticks;
if (previousWindowRectangle.IsEmpty || !frozen) {
if (previousWindowRectangle.IsEmpty || now - lastWindowRectangleRetrieveTime > CACHE_TIME) {
if (_previousWindowRectangle.IsEmpty || !_frozen) {
if (_previousWindowRectangle.IsEmpty || now - _lastWindowRectangleRetrieveTime > CacheTime) {
Rectangle windowRect = Rectangle.Empty;
if (DWM.isDWMEnabled()) {
GetExtendedFrameBounds(out windowRect);
if (DWM.IsDwmEnabled())
{
bool gotFrameBounds = GetExtendedFrameBounds(out windowRect);
if (IsApp)
{
// Pre-Cache for Maximised call, this is only on Windows 8 apps (full screen)
if (gotFrameBounds)
{
_previousWindowRectangle = windowRect;
_lastWindowRectangleRetrieveTime = now;
}
}
if (gotFrameBounds && Environment.OSVersion.IsWindows10() && !Maximised)
{
// Somehow DWM doesn't calculate it corectly, there is a 1 pixel border around the capture
// Remove this border, currently it's fixed but TODO: Make it depend on the OS?
windowRect.Inflate(-1, -1);
_previousWindowRectangle = windowRect;
_lastWindowRectangleRetrieveTime = now;
return windowRect;
}
}
if (windowRect.IsEmpty) {
GetWindowRect(out windowRect);
if (GetWindowRect(out windowRect))
{
Win32Error error = Win32.GetLastErrorCode();
LOG.WarnFormat("Couldn't retrieve the windows rectangle: {0}", Win32.GetMessage(error));
}
}
// Correction for maximized windows, only if it's not an app
if (!HasParent && !isApp && Maximised) {
Size size = Size.Empty;
GetBorderSize(out size);
windowRect = new Rectangle(windowRect.X + size.Width, windowRect.Y + size.Height, windowRect.Width - (2 * size.Width), windowRect.Height - (2 * size.Height));
if (!HasParent && !IsApp && Maximised) {
Size size;
// Only if the border size can be retrieved
if (GetBorderSize(out size))
{
windowRect = new Rectangle(windowRect.X + size.Width, windowRect.Y + size.Height, windowRect.Width - (2 * size.Width), windowRect.Height - (2 * size.Height));
}
}
lastWindowRectangleRetrieveTime = now;
_lastWindowRectangleRetrieveTime = now;
// Try to return something valid, by getting returning the previous size if the window doesn't have a Rectangle anymore
if (windowRect.IsEmpty) {
return previousWindowRectangle;
return _previousWindowRectangle;
}
previousWindowRectangle = windowRect;
_previousWindowRectangle = windowRect;
return windowRect;
}
}
return previousWindowRectangle;
return _previousWindowRectangle;
}
}
@ -819,8 +852,12 @@ namespace GreenshotPlugin.Core {
/// </summary>
public Rectangle ClientRectangle {
get {
Rectangle clientRect = Rectangle.Empty;
GetClientRect(out clientRect);
Rectangle clientRect;
if (GetClientRect(out clientRect))
{
Win32Error error = Win32.GetLastErrorCode();
LOG.WarnFormat("Couldn't retrieve the client rectangle for {0}, error: {1}", Text, Win32.GetMessage(error));
}
return clientRect;
}
}
@ -840,10 +877,10 @@ namespace GreenshotPlugin.Core {
/// </summary>
public void Restore() {
if (Iconic) {
User32.SendMessage(hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_RESTORE, IntPtr.Zero);
User32.SendMessage(_hWnd, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)User32.SC_RESTORE, IntPtr.Zero);
}
User32.BringWindowToTop(hWnd);
User32.SetForegroundWindow(hWnd);
User32.BringWindowToTop(_hWnd);
User32.SetForegroundWindow(_hWnd);
// Make sure windows has time to perform the action
while(Iconic) {
Application.DoEvents();
@ -855,10 +892,10 @@ namespace GreenshotPlugin.Core {
/// </summary>
public WindowStyleFlags WindowStyle {
get {
return (WindowStyleFlags)User32.GetWindowLongWrapper(hWnd, (int)WindowLongIndex.GWL_STYLE);
return (WindowStyleFlags)User32.GetWindowLongWrapper(_hWnd, (int)WindowLongIndex.GWL_STYLE);
}
set {
User32.SetWindowLongWrapper(hWnd, (int)WindowLongIndex.GWL_STYLE, new IntPtr((long)value));
User32.SetWindowLongWrapper(_hWnd, (int)WindowLongIndex.GWL_STYLE, new IntPtr((long)value));
}
}
@ -881,10 +918,10 @@ namespace GreenshotPlugin.Core {
/// </summary>
public ExtendedWindowStyleFlags ExtendedWindowStyle {
get {
return (ExtendedWindowStyleFlags)User32.GetWindowLongWrapper(hWnd, (int)WindowLongIndex.GWL_EXSTYLE);
return (ExtendedWindowStyleFlags)User32.GetWindowLongWrapper(_hWnd, (int)WindowLongIndex.GWL_EXSTYLE);
}
set {
User32.SetWindowLongWrapper(hWnd, (int)WindowLongIndex.GWL_EXSTYLE, new IntPtr((uint)value));
User32.SetWindowLongWrapper(_hWnd, (int)WindowLongIndex.GWL_EXSTYLE, new IntPtr((uint)value));
}
}
@ -893,7 +930,7 @@ namespace GreenshotPlugin.Core {
/// </summary>
/// <param name="capture">The capture to fill</param>
/// <returns>ICapture</returns>
public ICapture CaptureGDIWindow(ICapture capture) {
public ICapture CaptureGdiWindow(ICapture capture) {
Image capturedImage = PrintWindow();
if (capturedImage != null) {
capture.Image = capturedImage;
@ -910,15 +947,17 @@ namespace GreenshotPlugin.Core {
/// <param name="windowCaptureMode">Wanted WindowCaptureMode</param>
/// <param name="autoMode">True if auto modus is used</param>
/// <returns>ICapture with the capture</returns>
public ICapture CaptureDWMWindow(ICapture capture, WindowCaptureMode windowCaptureMode, bool autoMode) {
public ICapture CaptureDwmWindow(ICapture capture, WindowCaptureMode windowCaptureMode, bool autoMode) {
IntPtr thumbnailHandle = IntPtr.Zero;
Form tempForm = null;
bool tempFormShown = false;
try {
tempForm = new Form();
tempForm.ShowInTaskbar = false;
tempForm.FormBorderStyle = FormBorderStyle.None;
tempForm.TopMost = true;
tempForm = new Form
{
ShowInTaskbar = false,
FormBorderStyle = FormBorderStyle.None,
TopMost = true
};
// Register the Thumbnail
DWM.DwmRegisterThumbnail(tempForm.Handle, Handle, out thumbnailHandle);
@ -927,13 +966,13 @@ namespace GreenshotPlugin.Core {
SIZE sourceSize;
DWM.DwmQueryThumbnailSourceSize(thumbnailHandle, out sourceSize);
if (sourceSize.width <= 0 || sourceSize.height <= 0) {
if (sourceSize.Width <= 0 || sourceSize.Height <= 0) {
return null;
}
// Calculate the location of the temp form
Point formLocation;
Rectangle windowRectangle = WindowRectangle;
Point formLocation = windowRectangle.Location;
Size borderSize = new Size();
bool doesCaptureFit = false;
if (!Maximised) {
@ -942,7 +981,7 @@ namespace GreenshotPlugin.Core {
using (Region workingArea = new Region(Screen.PrimaryScreen.Bounds)) {
// Find the screen where the window is and check if it fits
foreach (Screen screen in Screen.AllScreens) {
if (screen != Screen.PrimaryScreen) {
if (!Equals(screen, Screen.PrimaryScreen)) {
workingArea.Union(screen.Bounds);
}
}
@ -962,7 +1001,7 @@ namespace GreenshotPlugin.Core {
doesCaptureFit = true;
}
}
} else {
} else if (!Environment.OSVersion.IsWindows8OrLater()) {
//GetClientRect(out windowRectangle);
GetBorderSize(out borderSize);
formLocation = new Point(windowRectangle.X - borderSize.Width, windowRectangle.Y - borderSize.Height);
@ -972,32 +1011,38 @@ namespace GreenshotPlugin.Core {
tempForm.Size = sourceSize.ToSize();
// Prepare rectangle to capture from the screen.
Rectangle captureRectangle = new Rectangle(formLocation.X, formLocation.Y, sourceSize.width, sourceSize.height);
Rectangle captureRectangle = new Rectangle(formLocation.X, formLocation.Y, sourceSize.Width, sourceSize.Height);
if (Maximised) {
// Correct capture size for maximized window by offsetting the X,Y with the border size
captureRectangle.X += borderSize.Width;
captureRectangle.Y += borderSize.Height;
// and subtracting the border from the size (2 times, as we move right/down for the capture without resizing)
captureRectangle.Width -= 2 * borderSize.Width;
captureRectangle.Height -= 2 * borderSize.Height;
} else if (autoMode) {
// check if the capture fits
if (!doesCaptureFit) {
// if GDI is allowed.. (a screenshot won't be better than we comes if we continue)
using (Process thisWindowProcess = Process) {
if (!isMetroApp && WindowCapture.IsGdiAllowed(thisWindowProcess)) {
// we return null which causes the capturing code to try another method.
return null;
captureRectangle.Inflate(borderSize.Width, borderSize.Height);
} else {
// TODO: Also 8.x?
if (Environment.OSVersion.IsWindows10())
{
captureRectangle.Inflate(-1, -1);
}
if (autoMode) {
// check if the capture fits
if (!doesCaptureFit) {
// if GDI is allowed.. (a screenshot won't be better than we comes if we continue)
using (Process thisWindowProcess = Process) {
if (!IsMetroApp && WindowCapture.IsGdiAllowed(thisWindowProcess)) {
// we return null which causes the capturing code to try another method.
return null;
}
}
}
}
}
// Prepare the displaying of the Thumbnail
DWM_THUMBNAIL_PROPERTIES props = new DWM_THUMBNAIL_PROPERTIES();
props.Opacity = (byte)255;
props.Visible = true;
props.Destination = new RECT(0, 0, sourceSize.width, sourceSize.height);
DWM_THUMBNAIL_PROPERTIES props = new DWM_THUMBNAIL_PROPERTIES
{
Opacity = 255,
Visible = true,
Destination = new RECT(0, 0, sourceSize.Width, sourceSize.Height)
};
DWM.DwmUpdateThumbnailProperties(thumbnailHandle, ref props);
tempForm.Show();
tempFormShown = true;
@ -1024,7 +1069,7 @@ namespace GreenshotPlugin.Core {
tempForm.BackColor = Color.Black;
// Make sure everything is visible
tempForm.Refresh();
if (!isMetroApp) {
if (!IsMetroApp) {
// Make sure the application window is active, so the colors & buttons are right
ToForeground();
}
@ -1047,7 +1092,7 @@ namespace GreenshotPlugin.Core {
if (capturedBitmap == null) {
// Remove transparency, this will break the capturing
if (!autoMode) {
tempForm.BackColor = Color.FromArgb(255, conf.DWMBackgroundColor.R, conf.DWMBackgroundColor.G, conf.DWMBackgroundColor.B);
tempForm.BackColor = Color.FromArgb(255, Conf.DWMBackgroundColor.R, Conf.DWMBackgroundColor.G, Conf.DWMBackgroundColor.B);
} else {
Color colorizationColor = DWM.ColorizationColor;
// Modify by losing the transparency and increasing the intensity (as if the background color is white)
@ -1056,7 +1101,7 @@ namespace GreenshotPlugin.Core {
}
// Make sure everything is visible
tempForm.Refresh();
if (!isMetroApp) {
if (!IsMetroApp) {
// Make sure the application window is active, so the colors & buttons are right
ToForeground();
}
@ -1067,9 +1112,9 @@ namespace GreenshotPlugin.Core {
}
if (capturedBitmap != null) {
// Not needed for Windows 8
if (!(Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 2)) {
if (!Environment.OSVersion.IsWindows8OrLater()) {
// Only if the Inivalue is set, not maximized and it's not a tool window.
if (conf.WindowCaptureRemoveCorners && !Maximised && (ExtendedWindowStyle & ExtendedWindowStyleFlags.WS_EX_TOOLWINDOW) == 0) {
if (Conf.WindowCaptureRemoveCorners && !Maximised && (ExtendedWindowStyle & ExtendedWindowStyleFlags.WS_EX_TOOLWINDOW) == 0) {
// Remove corners
if (!Image.IsAlphaPixelFormat(capturedBitmap.PixelFormat)) {
LOG.Debug("Changing pixelformat to Alpha for the RemoveCorners");
@ -1114,8 +1159,8 @@ namespace GreenshotPlugin.Core {
/// <param name="image">The bitmap to remove the corners from.</param>
private void RemoveCorners(Bitmap image) {
using (IFastBitmap fastBitmap = FastBitmap.Create(image)) {
for (int y = 0; y < conf.WindowCornerCutShape.Count; y++) {
for (int x = 0; x < conf.WindowCornerCutShape[y]; x++) {
for (int y = 0; y < Conf.WindowCornerCutShape.Count; y++) {
for (int x = 0; x < Conf.WindowCornerCutShape[y]; x++) {
fastBitmap.SetColorAt(x, y, Color.Transparent);
fastBitmap.SetColorAt(image.Width-1-x, y, Color.Transparent);
fastBitmap.SetColorAt(image.Width-1-x, image.Height-1-y, Color.Transparent);
@ -1222,7 +1267,7 @@ namespace GreenshotPlugin.Core {
/// <summary>
/// Helper method to get the Border size for GDI Windows
/// </summary>
/// <param name="rectangle">out Rectangle</param>
/// <param name="size">out Size</param>
/// <returns>bool true if it worked</returns>
private bool GetBorderSize(out Size size) {
WindowInfo windowInfo = new WindowInfo();
@ -1273,7 +1318,7 @@ namespace GreenshotPlugin.Core {
return false;
}
foreach (string excludeProcess in excludeProcessesFromFreeze) {
foreach (string excludeProcess in ExcludeProcessesFromFreeze) {
if (titleOrProcessname.ToLower().Contains(excludeProcess)) {
return false;
}
@ -1401,7 +1446,7 @@ namespace GreenshotPlugin.Core {
/// </summary>
/// <param name="hWnd">The Window Handle</param>
public WindowDetails(IntPtr hWnd) {
this.hWnd = hWnd;
this._hWnd = hWnd;
}
/// <summary>
@ -1411,7 +1456,7 @@ namespace GreenshotPlugin.Core {
public static WindowDetails GetActiveWindow() {
IntPtr hWnd = User32.GetForegroundWindow();
if (hWnd != null && hWnd != IntPtr.Zero) {
if (ignoreHandles.Contains(hWnd)) {
if (IgnoreHandles.Contains(hWnd)) {
return GetDesktopWindow();
}
@ -1431,7 +1476,7 @@ namespace GreenshotPlugin.Core {
public bool IsGreenshot {
get {
try {
if (!isMetroApp) {
if (!IsMetroApp) {
using (Process thisWindowProcess = Process) {
return "Greenshot".Equals(thisWindowProcess.MainModule.FileVersionInfo.ProductName);
}
@ -1462,7 +1507,7 @@ namespace GreenshotPlugin.Core {
/// <summary>
/// Get all the top level windows, with matching classname
/// </summary>
/// <returns>List<WindowDetails> with all the top level windows</returns>
/// <returns>List WindowDetails with all the top level windows</returns>
public static List<WindowDetails> GetAllWindows(string classname) {
return new WindowsEnumerator().GetWindows(IntPtr.Zero, classname).Items;
}
@ -1470,7 +1515,6 @@ namespace GreenshotPlugin.Core {
/// <summary>
/// Recursive "find children which"
/// </summary>
/// <param name="window">Window to look into</param>
/// <param name="point">point to check for</param>
/// <returns></returns>
public WindowDetails FindChildUnderPoint(Point point) {
@ -1499,7 +1543,7 @@ namespace GreenshotPlugin.Core {
/// <summary>
/// Get all the visible top level windows
/// </summary>
/// <returns>List<WindowDetails> with all the visible top level windows</returns>
/// <returns>List WindowDetails with all the visible top level windows</returns>
public static List<WindowDetails> GetVisibleWindows() {
List<WindowDetails> windows = new List<WindowDetails>();
Rectangle screenBounds = WindowCapture.GetScreenBounds();
@ -1515,7 +1559,7 @@ namespace GreenshotPlugin.Core {
continue;
}
// Ignore some classes
List<string> ignoreClasses = new List<string>(new string[] { "Progman", "XLMAIN", "Button", "Dwm" }); //"MS-SDIa"
List<string> ignoreClasses = new List<string>(new[] { "Progman", "XLMAIN", "Button", "Dwm" }); //"MS-SDIa"
if (ignoreClasses.Contains(window.ClassName)) {
continue;
}
@ -1534,7 +1578,7 @@ namespace GreenshotPlugin.Core {
/// Get the WindowDetails for all Metro Apps
/// These are all Windows with Classname "Windows.UI.Core.CoreWindow"
/// </summary>
/// <returns>List<WindowDetails> with visible metro apps</returns>
/// <returns>List WindowDetails with visible metro apps</returns>
public static List<WindowDetails> GetMetroApps() {
List<WindowDetails> metroApps = new List<WindowDetails>();
// if the appVisibility != null we have Windows 8.
@ -1574,7 +1618,7 @@ namespace GreenshotPlugin.Core {
/// <summary>
/// Get all the top level windows
/// </summary>
/// <returns>List<WindowDetails> with all the top level windows</returns>
/// <returns>List WindowDetails with all the top level windows</returns>
public static List<WindowDetails> GetTopLevelWindows() {
List<WindowDetails> windows = new List<WindowDetails>();
var possibleTopLevelWindows = GetMetroApps();
@ -1585,7 +1629,7 @@ namespace GreenshotPlugin.Core {
continue;
}
// Ignore some classes
List<string> ignoreClasses = new List<string>(new string[] { "Progman", "XLMAIN", "Button", "Dwm" }); //"MS-SDIa"
List<string> ignoreClasses = new List<string>(new[] { "Progman", "XLMAIN", "Button", "Dwm" }); //"MS-SDIa"
if (ignoreClasses.Contains(window.ClassName)) {
continue;
}
@ -1652,7 +1696,7 @@ namespace GreenshotPlugin.Core {
/// Helper method to "active" all windows that are not in the supplied list.
/// One should preferably call "GetVisibleWindows" for the oldWindows.
/// </summary>
/// <param name="oldWindows">List<WindowDetails> with old windows</param>
/// <param name="oldWindows">List WindowDetails with old windows</param>
public static void ActiveNewerWindows(List<WindowDetails> oldWindows) {
List<WindowDetails> windowsAfter = GetVisibleWindows();
foreach(WindowDetails window in windowsAfter) {