Code quality changes for stability and reduced memory usage.

This commit is contained in:
RKrom 2014-06-13 12:18:59 +02:00
commit 08216b09c0
21 changed files with 342 additions and 316 deletions

View file

@ -596,9 +596,10 @@ namespace Greenshot.Helpers {
ProcessStartInfo psi = new ProcessStartInfo("explorer.exe");
psi.Arguments = Path.GetDirectoryName(surface.LastSaveFullPath);
psi.UseShellExecute = false;
Process p = new Process();
p.StartInfo = psi;
p.Start();
using (Process p = new Process()) {
p.StartInfo = psi;
p.Start();
}
} catch (Exception ex) {
errorMessage = ex.Message;
}
@ -611,9 +612,10 @@ namespace Greenshot.Helpers {
ProcessStartInfo psi = new ProcessStartInfo(explorerPath);
psi.Arguments = Path.GetDirectoryName(surface.LastSaveFullPath);
psi.UseShellExecute = false;
Process p = new Process();
p.StartInfo = psi;
p.Start();
using (Process p = new Process()) {
p.StartInfo = psi;
p.Start();
}
errorMessage = null;
}
} catch {
@ -783,151 +785,152 @@ namespace Greenshot.Helpers {
// When Vista & DWM (Aero) enabled
bool dwmEnabled = DWM.isDWMEnabled();
// get process name to be able to exclude certain processes from certain capture modes
Process process = windowToCapture.Process;
bool isAutoMode = windowCaptureMode == WindowCaptureMode.Auto;
// For WindowCaptureMode.Auto we check:
// 1) Is window IE, use IE Capture
// 2) Is Windows >= Vista & DWM enabled: use DWM
// 3) Otherwise use GDI (Screen might be also okay but might lose content)
if (isAutoMode) {
if (conf.IECapture && IECaptureHelper.IsIEWindow(windowToCapture)) {
try {
ICapture ieCapture = IECaptureHelper.CaptureIE(captureForWindow, windowToCapture);
if (ieCapture != null) {
return ieCapture;
using (Process process = windowToCapture.Process) {
bool isAutoMode = windowCaptureMode == WindowCaptureMode.Auto;
// For WindowCaptureMode.Auto we check:
// 1) Is window IE, use IE Capture
// 2) Is Windows >= Vista & DWM enabled: use DWM
// 3) Otherwise use GDI (Screen might be also okay but might lose content)
if (isAutoMode) {
if (conf.IECapture && IECaptureHelper.IsIEWindow(windowToCapture)) {
try {
ICapture ieCapture = IECaptureHelper.CaptureIE(captureForWindow, windowToCapture);
if (ieCapture != null) {
return ieCapture;
}
} catch (Exception ex) {
LOG.WarnFormat("Problem capturing IE, skipping to normal capture. Exception message was: {0}", ex.Message);
}
} catch (Exception ex) {
LOG.WarnFormat("Problem capturing IE, skipping to normal capture. Exception message was: {0}", ex.Message);
}
}
// Take default screen
windowCaptureMode = WindowCaptureMode.Screen;
// Change to GDI, if allowed
if (!windowToCapture.isMetroApp && WindowCapture.isGDIAllowed(process)) {
if (!dwmEnabled && isWPF(process)) {
// do not use GDI, as DWM is not enabled and the application uses PresentationFramework.dll -> isWPF
LOG.InfoFormat("Not using GDI for windows of process {0}, as the process uses WPF", process.ProcessName);
} else {
windowCaptureMode = WindowCaptureMode.GDI;
}
}
// Change to DWM, if enabled and allowed
if (dwmEnabled) {
if (windowToCapture.isMetroApp || WindowCapture.isDWMAllowed(process)) {
windowCaptureMode = WindowCaptureMode.Aero;
}
}
} else if (windowCaptureMode == WindowCaptureMode.Aero || windowCaptureMode == WindowCaptureMode.AeroTransparent) {
if (!dwmEnabled || (!windowToCapture.isMetroApp && !WindowCapture.isDWMAllowed(process))) {
// Take default screen
windowCaptureMode = WindowCaptureMode.Screen;
// Change to GDI, if allowed
if (WindowCapture.isGDIAllowed(process)) {
windowCaptureMode = WindowCaptureMode.GDI;
}
}
} else if (windowCaptureMode == WindowCaptureMode.GDI && !WindowCapture.isGDIAllowed(process)) {
// GDI not allowed, take screen
windowCaptureMode = WindowCaptureMode.Screen;
}
LOG.InfoFormat("Capturing window with mode {0}", windowCaptureMode);
bool captureTaken = false;
windowRectangle.Intersect(captureForWindow.ScreenBounds);
// Try to capture
while (!captureTaken) {
ICapture tmpCapture = null;
switch (windowCaptureMode) {
case WindowCaptureMode.GDI:
// Change to GDI, if allowed
if (!windowToCapture.isMetroApp && WindowCapture.isGDIAllowed(process)) {
if (!dwmEnabled && isWPF(process)) {
// do not use GDI, as DWM is not enabled and the application uses PresentationFramework.dll -> isWPF
LOG.InfoFormat("Not using GDI for windows of process {0}, as the process uses WPF", process.ProcessName);
} else {
windowCaptureMode = WindowCaptureMode.GDI;
}
}
// Change to DWM, if enabled and allowed
if (dwmEnabled) {
if (windowToCapture.isMetroApp || WindowCapture.isDWMAllowed(process)) {
windowCaptureMode = WindowCaptureMode.Aero;
}
}
} else if (windowCaptureMode == WindowCaptureMode.Aero || windowCaptureMode == WindowCaptureMode.AeroTransparent) {
if (!dwmEnabled || (!windowToCapture.isMetroApp && !WindowCapture.isDWMAllowed(process))) {
// Take default screen
windowCaptureMode = WindowCaptureMode.Screen;
// Change to GDI, if allowed
if (WindowCapture.isGDIAllowed(process)) {
windowCaptureMode = WindowCaptureMode.GDI;
}
}
} else if (windowCaptureMode == WindowCaptureMode.GDI && !WindowCapture.isGDIAllowed(process)) {
// GDI not allowed, take screen
windowCaptureMode = WindowCaptureMode.Screen;
}
LOG.InfoFormat("Capturing window with mode {0}", windowCaptureMode);
bool captureTaken = false;
windowRectangle.Intersect(captureForWindow.ScreenBounds);
// Try to capture
while (!captureTaken) {
ICapture tmpCapture = null;
switch (windowCaptureMode) {
case WindowCaptureMode.GDI:
if (WindowCapture.isGDIAllowed(process)) {
if (windowToCapture.Iconic) {
// Restore the window making sure it's visible!
windowToCapture.Restore();
} else {
windowToCapture.ToForeground();
}
tmpCapture = windowToCapture.CaptureGDIWindow(captureForWindow);
if (tmpCapture != null) {
// check if GDI capture any good, by comparing it with the screen content
int blackCountGDI = ImageHelper.CountColor((Bitmap)tmpCapture.Image, Color.Black, false);
int GDIPixels = tmpCapture.Image.Width * tmpCapture.Image.Height;
int blackPercentageGDI = (blackCountGDI * 100) / GDIPixels;
if (blackPercentageGDI >= 1) {
int screenPixels = windowRectangle.Width * windowRectangle.Height;
using (ICapture screenCapture = new Capture()) {
screenCapture.CaptureDetails = captureForWindow.CaptureDetails;
if (WindowCapture.CaptureRectangle(screenCapture, windowRectangle) != null) {
int blackCountScreen = ImageHelper.CountColor((Bitmap)screenCapture.Image, Color.Black, false);
int blackPercentageScreen = (blackCountScreen * 100) / screenPixels;
if (screenPixels == GDIPixels) {
// "easy compare", both have the same size
// If GDI has more black, use the screen capture.
if (blackPercentageGDI > blackPercentageScreen) {
LOG.Debug("Using screen capture, as GDI had additional black.");
// changeing the image will automatically dispose the previous
tmpCapture.Image = screenCapture.Image;
// Make sure it's not disposed, else the picture is gone!
screenCapture.NullImage();
}
} else if (screenPixels < GDIPixels) {
// Screen capture is cropped, window is outside of screen
if (blackPercentageGDI > 50 && blackPercentageGDI > blackPercentageScreen) {
LOG.Debug("Using screen capture, as GDI had additional black.");
// changeing the image will automatically dispose the previous
tmpCapture.Image = screenCapture.Image;
// Make sure it's not disposed, else the picture is gone!
screenCapture.NullImage();
}
} else {
// Use the GDI capture by doing nothing
LOG.Debug("This should not happen, how can there be more screen as GDI pixels?");
}
}
}
}
}
}
if (tmpCapture != null) {
captureForWindow = tmpCapture;
captureTaken = true;
} else {
// A problem, try Screen
windowCaptureMode = WindowCaptureMode.Screen;
}
break;
case WindowCaptureMode.Aero:
case WindowCaptureMode.AeroTransparent:
if (windowToCapture.isMetroApp || WindowCapture.isDWMAllowed(process)) {
tmpCapture = windowToCapture.CaptureDWMWindow(captureForWindow, windowCaptureMode, isAutoMode);
}
if (tmpCapture != null) {
captureForWindow = tmpCapture;
captureTaken = true;
} else {
// A problem, try GDI
windowCaptureMode = WindowCaptureMode.GDI;
}
break;
default:
// Screen capture
if (windowToCapture.Iconic) {
// Restore the window making sure it's visible!
windowToCapture.Restore();
} else {
windowToCapture.ToForeground();
}
tmpCapture = windowToCapture.CaptureGDIWindow(captureForWindow);
if (tmpCapture != null) {
// check if GDI capture any good, by comparing it with the screen content
int blackCountGDI = ImageHelper.CountColor((Bitmap)tmpCapture.Image, Color.Black, false);
int GDIPixels = tmpCapture.Image.Width * tmpCapture.Image.Height;
int blackPercentageGDI = (blackCountGDI * 100) / GDIPixels;
if (blackPercentageGDI >= 1) {
int screenPixels = windowRectangle.Width * windowRectangle.Height;
using (ICapture screenCapture = new Capture()) {
screenCapture.CaptureDetails = captureForWindow.CaptureDetails;
if (WindowCapture.CaptureRectangle(screenCapture, windowRectangle) != null) {
int blackCountScreen = ImageHelper.CountColor((Bitmap)screenCapture.Image, Color.Black, false);
int blackPercentageScreen = (blackCountScreen * 100) / screenPixels;
if (screenPixels == GDIPixels) {
// "easy compare", both have the same size
// If GDI has more black, use the screen capture.
if (blackPercentageGDI > blackPercentageScreen) {
LOG.Debug("Using screen capture, as GDI had additional black.");
// changeing the image will automatically dispose the previous
tmpCapture.Image = screenCapture.Image;
// Make sure it's not disposed, else the picture is gone!
screenCapture.NullImage();
}
} else if (screenPixels < GDIPixels) {
// Screen capture is cropped, window is outside of screen
if (blackPercentageGDI > 50 && blackPercentageGDI > blackPercentageScreen) {
LOG.Debug("Using screen capture, as GDI had additional black.");
// changeing the image will automatically dispose the previous
tmpCapture.Image = screenCapture.Image;
// Make sure it's not disposed, else the picture is gone!
screenCapture.NullImage();
}
} else {
// Use the GDI capture by doing nothing
LOG.Debug("This should not happen, how can there be more screen as GDI pixels?");
}
}
}
}
}
}
if (tmpCapture != null) {
captureForWindow = tmpCapture;
captureTaken = true;
} else {
// A problem, try Screen
windowCaptureMode = WindowCaptureMode.Screen;
}
break;
case WindowCaptureMode.Aero:
case WindowCaptureMode.AeroTransparent:
if (windowToCapture.isMetroApp || WindowCapture.isDWMAllowed(process)) {
tmpCapture = windowToCapture.CaptureDWMWindow(captureForWindow, windowCaptureMode, isAutoMode);
}
if (tmpCapture != null) {
captureForWindow = tmpCapture;
captureTaken = true;
} else {
// A problem, try GDI
windowCaptureMode = WindowCaptureMode.GDI;
}
break;
default:
// Screen capture
if (windowToCapture.Iconic) {
// Restore the window making sure it's visible!
windowToCapture.Restore();
} else {
windowToCapture.ToForeground();
}
try {
captureForWindow = WindowCapture.CaptureRectangle(captureForWindow, windowRectangle);
captureTaken = true;
} catch (Exception e) {
LOG.Error("Problem capturing", e);
return null;
}
break;
try {
captureForWindow = WindowCapture.CaptureRectangle(captureForWindow, windowRectangle);
captureTaken = true;
} catch (Exception e) {
LOG.Error("Problem capturing", e);
return null;
}
break;
}
}
}

View file

@ -191,7 +191,7 @@ namespace Greenshot.Helpers {
/// Contains data and other information associated with data
/// which has been sent from another application.
/// </summary>
public class CopyDataReceivedEventArgs {
public class CopyDataReceivedEventArgs : EventArgs {
private string channelName = "";
private object data = null;
private DateTime sent;
@ -365,12 +365,12 @@ namespace Greenshot.Helpers {
[DllImport("user32", CharSet=CharSet.Unicode, SetLastError = true)]
private extern static IntPtr GetProp(IntPtr hwnd, string lpString);
[DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)]
private extern static IntPtr SetProp(IntPtr hwnd, string lpString, int hData);
private extern static bool SetProp(IntPtr hwnd, string lpString, IntPtr hData);
[DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)]
private extern static IntPtr RemoveProp(IntPtr hwnd, string lpString);
[DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)]
private extern static IntPtr SendMessage(IntPtr hwnd, int wMsg, int wParam, ref COPYDATASTRUCT lParam);
private extern static IntPtr SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, ref COPYDATASTRUCT lParam);
[StructLayout(LayoutKind.Sequential)]
private struct COPYDATASTRUCT {
@ -448,7 +448,7 @@ namespace Greenshot.Helpers {
cds.cbData = dataSize;
cds.dwData = IntPtr.Zero;
cds.lpData = ptrData;
SendMessage(window.Handle, WM_COPYDATA, (int)owner.Handle, ref cds);
SendMessage(window.Handle, WM_COPYDATA, owner.Handle, ref cds);
recipients += (Marshal.GetLastWin32Error() == 0 ? 1 : 0);
}
}
@ -464,7 +464,7 @@ namespace Greenshot.Helpers {
private void addChannel() {
// Tag this window with property "channelName"
SetProp(owner.Handle, channelName, (int)owner.Handle);
SetProp(owner.Handle, channelName, owner.Handle);
}
private void removeChannel() {
@ -515,7 +515,7 @@ namespace Greenshot.Helpers {
}
~CopyDataChannel() {
Dispose();
Dispose(false);
}
}

View file

@ -504,7 +504,7 @@ namespace Greenshot.Helpers {
public IntPtr EntryID = IntPtr.Zero;
}
[DllImport("MAPI32.DLL", SetLastError = true)]
[DllImport("MAPI32.DLL", SetLastError = true, CharSet=CharSet.Unicode)]
public static extern int MAPISendMail(IntPtr session, IntPtr hwnd, MapiMessage message, int flg, int rsv);
#endregion Structs