From fbc0285c93716e2e9a106ef2989aa627d6977157 Mon Sep 17 00:00:00 2001 From: RKrom Date: Tue, 23 Oct 2012 11:08:11 +0000 Subject: [PATCH] Added "special" DIB clipboard reader code, which is a test to fix bug #3576125. This is enabled over the ini property EnableSpecialDIBClipboardReader, disabled by default. git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@2195 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4 --- GreenshotPlugin/Core/BinaryStructHelper.cs | 72 ++++++++++++++++++++++ GreenshotPlugin/Core/ClipboardHelper.cs | 33 +++++++++- GreenshotPlugin/Core/CoreConfiguration.cs | 3 + GreenshotPlugin/Core/IEHelper.cs | 3 + GreenshotPlugin/GreenshotPlugin.csproj | 1 + GreenshotPlugin/UnmanagedHelpers/GDI32.cs | 12 +++- 6 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 GreenshotPlugin/Core/BinaryStructHelper.cs diff --git a/GreenshotPlugin/Core/BinaryStructHelper.cs b/GreenshotPlugin/Core/BinaryStructHelper.cs new file mode 100644 index 000000000..af3c96398 --- /dev/null +++ b/GreenshotPlugin/Core/BinaryStructHelper.cs @@ -0,0 +1,72 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +using System; +using System.Runtime.InteropServices; + +namespace GreenshotPlugin.Core { + /// + /// A helper class which does the mashalling for structs + /// + public static class BinaryStructHelper { + /// + /// Get a struct from a byte array + /// + /// typeof struct + /// byte[] + /// struct + public static T FromByteArray(byte[] bytes) where T : struct { + IntPtr ptr = IntPtr.Zero; + try { + int size = Marshal.SizeOf(typeof(T)); + ptr = Marshal.AllocHGlobal(size); + Marshal.Copy(bytes, 0, ptr, size); + object obj = Marshal.PtrToStructure(ptr, typeof(T)); + return (T)obj; + } finally { + if (ptr != IntPtr.Zero) { + Marshal.FreeHGlobal(ptr); + } + } + } + + /// + /// copy a struct to a byte array + /// + /// typeof struct + /// struct + /// byte[] + public static byte[] ToByteArray(T obj) where T : struct { + IntPtr ptr = IntPtr.Zero; + try { + int size = Marshal.SizeOf(typeof(T)); + ptr = Marshal.AllocHGlobal(size); + Marshal.StructureToPtr(obj, ptr, true); + byte[] bytes = new byte[size]; + Marshal.Copy(ptr, bytes, 0, size); + return bytes; + } finally { + if (ptr != IntPtr.Zero) { + Marshal.FreeHGlobal(ptr); + } + } + } + } +} diff --git a/GreenshotPlugin/Core/ClipboardHelper.cs b/GreenshotPlugin/Core/ClipboardHelper.cs index dcb0ae935..c1eab0366 100644 --- a/GreenshotPlugin/Core/ClipboardHelper.cs +++ b/GreenshotPlugin/Core/ClipboardHelper.cs @@ -22,7 +22,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; -using System.Drawing.Imaging; using System.IO; using System.Text; using System.Threading; @@ -30,6 +29,7 @@ using System.Windows.Forms; using Greenshot.IniFile; using Greenshot.Plugin; using GreenshotPlugin.UnmanagedHelpers; +using System.Runtime.InteropServices; namespace GreenshotPlugin.Core { /// @@ -238,6 +238,37 @@ EndSelection:<<<<<<<4 } } } + // If the EnableSpecialDIBClipboardReader flag in the config is set, use the code from: + // http://www.thomaslevesque.com/2009/02/05/wpf-paste-an-image-from-the-clipboard/ + // to read the DeviceIndependentBitmap from the clipboard, this might fix bug 3576125 + if (config.EnableSpecialDIBClipboardReader) { + MemoryStream ms = Clipboard.GetData("DeviceIndependentBitmap") as MemoryStream; + if (ms != null) { + byte[] dibBuffer = new byte[ms.Length]; + ms.Read(dibBuffer, 0, dibBuffer.Length); + BitmapInfoHeader infoHeader = BinaryStructHelper.FromByteArray(dibBuffer); + + int fileHeaderSize = Marshal.SizeOf(typeof(BitmapFileHeader)); + uint infoHeaderSize = infoHeader.biSize; + int fileSize = (int)(fileHeaderSize + infoHeader.biSize + infoHeader.biSizeImage); + + BitmapFileHeader fileHeader = new BitmapFileHeader(); + fileHeader.bfType = BitmapFileHeader.BM; + fileHeader.bfSize = fileSize; + fileHeader.bfReserved1 = 0; + fileHeader.bfReserved2 = 0; + fileHeader.bfOffBits = (int)(fileHeaderSize + infoHeaderSize + infoHeader.biClrUsed * 4); + + byte[] fileHeaderBytes = BinaryStructHelper.ToByteArray(fileHeader); + + using (MemoryStream msBitmap = new MemoryStream()) { + msBitmap.Write(fileHeaderBytes, 0, fileHeaderSize); + msBitmap.Write(dibBuffer, 0, dibBuffer.Length); + msBitmap.Seek(0, SeekOrigin.Begin); + return Image.FromStream(msBitmap); + } + } + } return Clipboard.GetImage(); } catch (Exception ee) { if (retryCount == 0) { diff --git a/GreenshotPlugin/Core/CoreConfiguration.cs b/GreenshotPlugin/Core/CoreConfiguration.cs index 96591f3c7..1ec077e94 100644 --- a/GreenshotPlugin/Core/CoreConfiguration.cs +++ b/GreenshotPlugin/Core/CoreConfiguration.cs @@ -191,6 +191,9 @@ namespace GreenshotPlugin.Core { [IniProperty("ExperimentalFeatures", Description="A list of experimental features, this allows us to test certain features before releasing them.", ExcludeIfNull=true)] public List ExperimentalFeatures; + [IniProperty("EnableSpecialDIBClipboardReader", Description = "Enable a special DIB clipboard reader", DefaultValue="False")] + public bool EnableSpecialDIBClipboardReader; + // Specify what THIS build is public bool isRelease = false; public bool isReleaseCandidate = true; diff --git a/GreenshotPlugin/Core/IEHelper.cs b/GreenshotPlugin/Core/IEHelper.cs index 2283daf44..481911d41 100644 --- a/GreenshotPlugin/Core/IEHelper.cs +++ b/GreenshotPlugin/Core/IEHelper.cs @@ -52,6 +52,9 @@ namespace GreenshotPlugin.Core { /// The browser WindowDetails /// WindowDetails for the DirectUI window public static WindowDetails GetDirectUI(WindowDetails browserWindowDetails) { + if (browserWindowDetails == null) { + return null; + } WindowDetails tmpWD = browserWindowDetails; // Since IE 9 the TabBandClass is less deep! if (IEHelper.IEVersion() < 9) { diff --git a/GreenshotPlugin/GreenshotPlugin.csproj b/GreenshotPlugin/GreenshotPlugin.csproj index 99dd85b8f..cbba0de09 100644 --- a/GreenshotPlugin/GreenshotPlugin.csproj +++ b/GreenshotPlugin/GreenshotPlugin.csproj @@ -198,6 +198,7 @@ + diff --git a/GreenshotPlugin/UnmanagedHelpers/GDI32.cs b/GreenshotPlugin/UnmanagedHelpers/GDI32.cs index c1262f850..8868271c1 100644 --- a/GreenshotPlugin/UnmanagedHelpers/GDI32.cs +++ b/GreenshotPlugin/UnmanagedHelpers/GDI32.cs @@ -46,7 +46,17 @@ namespace GreenshotPlugin.UnmanagedHelpers { [DllImport("gdi32", SetLastError = true)] public static extern uint GetPixel(IntPtr hdc, int nXPos, int nYPos); } - + + [StructLayout(LayoutKind.Sequential, Pack = 2)] + public struct BitmapFileHeader { + public static readonly short BM = 0x4d42; // BM + public short bfType; + public int bfSize; + public short bfReserved1; + public short bfReserved2; + public int bfOffBits; + } + [StructLayout(LayoutKind.Sequential)] public struct BitmapInfoHeader { public uint biSize;