Skip to content

Commit

Permalink
Fixed images from clipboard sometimes not working
Browse files Browse the repository at this point in the history
Added unhandied exception logging
  • Loading branch information
Filipsi committed Nov 17, 2019
1 parent 1c93b40 commit fe76275
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@
<Compile Include="DataStorage\Schema\Color.cs" />
<Compile Include="DataStorage\Schema\Tag.cs" />
<Compile Include="DataStorage\Schema\TagType.cs" />
<Compile Include="Services\Clipboard\BinaryStructConverter.cs" />
<Compile Include="Services\Clipboard\ClipboardEventArgs.cs" />
<Compile Include="Services\Clipboard\ClipboardService.cs" />
<Compile Include="Services\Clipboard\IClipboardService.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using System.Runtime.InteropServices;

namespace ClipboardMachinery.Core.Services.Clipboard {

public static class BinaryStructConverter {
public static T FromByteArray<T>(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);
return (T)Marshal.PtrToStructure(ptr, typeof(T));
} finally {
if (ptr != IntPtr.Zero) {
Marshal.FreeHGlobal(ptr);
}
}
}

public static byte[] ToByteArray<T>(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);
}
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Castle.Core.Logging;
using WinClipboard = System.Windows.Clipboard;
Expand Down Expand Up @@ -113,7 +114,7 @@ private string GetClipboardContent() {

// ReSharper disable once InvertIf
if (WinClipboard.ContainsImage()) {
BitmapSource bitmap = WinClipboard.GetImage();
BitmapSource bitmap = GetBitmapFromClipboardDib();

if (bitmap != null) {
using (MemoryStream rawImage = new MemoryStream()) {
Expand All @@ -130,6 +131,44 @@ private string GetClipboardContent() {
return string.Empty;
}

private static BitmapSource GetBitmapFromClipboardDib() {
MemoryStream ms = (MemoryStream) WinClipboard.GetData(DataFormats.Dib);

if (ms == null) {
return null;
}

byte[] dibBuffer = new byte[ms.Length];
ms.Read(dibBuffer, 0, dibBuffer.Length);

BITMAPINFOHEADER infoHeader = BinaryStructConverter.FromByteArray<BITMAPINFOHEADER>(
bytes: dibBuffer
);

int fileHeaderSize = Marshal.SizeOf(typeof(BITMAPFILEHEADER));
int infoHeaderSize = infoHeader.biSize;
int fileSize = fileHeaderSize + infoHeader.biSize + infoHeader.biSizeImage;

BITMAPFILEHEADER fileHeader = new BITMAPFILEHEADER {
bfType = BITMAPFILEHEADER.BM,
bfSize = fileSize,
bfReserved1 = 0,
bfReserved2 = 0,
bfOffBits = fileHeaderSize + infoHeaderSize + infoHeader.biClrUsed * 4
};

byte[] fileHeaderBytes = BinaryStructConverter.ToByteArray(
obj: fileHeader
);

MemoryStream msBitmap = new MemoryStream();
msBitmap.Write(fileHeaderBytes, 0, fileHeaderSize);
msBitmap.Write(dibBuffer, 0, dibBuffer.Length);
msBitmap.Seek(0, SeekOrigin.Begin);

return BitmapFrame.Create(msBitmap);
}

#endregion

#region Handlers
Expand All @@ -149,6 +188,32 @@ private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref b

#endregion

[StructLayout(LayoutKind.Sequential, Pack = 2)]
private struct BITMAPFILEHEADER {
public static readonly short BM = 0x4d42;

public short bfType;
public int bfSize;
public short bfReserved1;
public short bfReserved2;
public int bfOffBits;
}

[StructLayout(LayoutKind.Sequential)]
private struct BITMAPINFOHEADER {
public readonly int biSize;
private readonly int biWidth;
private readonly int biHeight;
private readonly short biPlanes;
private readonly short biBitCount;
private readonly int biCompression;
public readonly int biSizeImage;
private readonly int biXPelsPerMeter;
private readonly int biYPelsPerMeter;
public readonly int biClrUsed;
private readonly int biClrImportant;
}

private static class NativeMethods {

// http://msdn.microsoft.com/en-us/library/ms649021%28v=vs.85%29.aspx
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Threading;
using Caliburn.Micro;
using Castle.Core.Logging;
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel.Resolvers.SpecializedResolvers;
using Castle.Windsor;
Expand All @@ -18,6 +20,7 @@ internal class AppBootstrapper : BootstrapperBase {
public const string REPOSITORY_NAME = "ClipboardMachinery";

private readonly IWindsorContainer container = new WindsorContainer();
private ILogger logger;

#endregion

Expand All @@ -38,6 +41,8 @@ protected override void Configure() {
.AddFacility<EventAggregatorFacility>()
.Install(FromAssembly.Named("ClipboardMachinery.Core"))
.Install(FromAssembly.This());

logger = container.Resolve<ILogger>();
}

protected override object GetInstance(Type service, string key) {
Expand All @@ -52,6 +57,10 @@ protected override async void OnStartup(object sender, StartupEventArgs e) {
await DisplayRootViewForAsync(typeof(IShell));
}

protected override void OnUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) {
logger.Fatal("Encountered fatal error!", e.Exception);
}

protected override void OnExit(object sender, EventArgs e) {
container.Dispose();
base.OnExit(sender, e);
Expand Down

0 comments on commit fe76275

Please sign in to comment.