Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor existing Clipboard code #10495

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable enable

// Description: Helper methods for code that uses types from System.Drawing.

Expand All @@ -16,61 +17,30 @@
namespace MS.Internal
{
//FxCop can't tell that this class is instantiated via reflection, so suppress the FxCop warning.
[SuppressMessage("Microsoft.Performance","CA1812:AvoidUninstantiatedInternalClasses")]
[SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")]
internal class SystemDrawingExtension : SystemDrawingExtensionMethods
{
// return true if the data is a bitmap
internal override bool IsBitmap(object data)
{
return data is Bitmap;
}
internal override bool IsBitmap(object? data) => data is Bitmap;

// return true if the data is an Image
internal override bool IsImage(object data)
{
return data is Image;
}
internal override bool IsImage(object? data) => data is Image;

// return true if the data is a graphics metafile
internal override bool IsMetafile(object data)
{
return data is Metafile;
}
internal override bool IsMetafile(object? data) => data is Metafile;

// return the handle from a metafile
internal override IntPtr GetHandleFromMetafile(Object data)
internal override nint GetHandleFromMetafile(object? data) => data switch
{
IntPtr hMetafile = IntPtr.Zero;
Metafile metafile = data as Metafile;

if (metafile != null)
{
// Get the Windows handle from the metafile object.
hMetafile = metafile.GetHenhmetafile();
}
Metafile metafile => metafile.GetHenhmetafile(),
_ => 0
};

return hMetafile;
}
internal override object GetMetafileFromHemf(nint hMetafile) => new Metafile(hMetafile, deleteEmf: false);

// Get the metafile from the handle of the enhanced metafile.
internal override Object GetMetafileFromHemf(IntPtr hMetafile)
{
return new Metafile(hMetafile, false);
}

// Get a bitmap from the given data (either BitmapSource or Bitmap)
internal override object GetBitmap(object data)
{
return GetBitmapImpl(data);
}
internal override object? GetBitmap(object? data) => GetBitmapImpl(data);

// Get a bitmap handle from the given data (either BitmapSource or Bitmap)
// Also return its width and height.
internal override IntPtr GetHBitmap(object data, out int width, out int height)
internal override nint GetHBitmap(object? data, out int width, out int height)
{
Bitmap bitmapData = GetBitmapImpl(data);
Bitmap? bitmapData = GetBitmapImpl(data);

if (bitmapData == null)
if (bitmapData is null)
{
width = height = 0;
return IntPtr.Zero;
Expand All @@ -84,54 +54,45 @@ internal override IntPtr GetHBitmap(object data, out int width, out int height)
return bitmapData.GetHbitmap();
}

// Get a bitmap handle from a Bitmap
internal override IntPtr GetHBitmapFromBitmap(object data)
{
Bitmap bitmap = data as Bitmap;
return (bitmap != null) ? bitmap.GetHbitmap() : IntPtr.Zero;
}
internal override nint GetHBitmapFromBitmap(object? data) => data is Bitmap bitmap ? bitmap.GetHbitmap() : 0;

// Convert a metafile to HBitmap
internal override IntPtr ConvertMetafileToHBitmap(IntPtr handle)
internal override nint ConvertMetafileToHBitmap(nint handle)
{
Metafile metafile = new Metafile(handle, false);
Metafile metafile = new(handle, deleteEmf: false);

// Initialize the bitmap size to render the metafile.
int bitmapheight = metafile.Size.Height;
int bitmapwidth = metafile.Size.Width;
int bitmapwidth = metafile.Size.Width;

// We use System.Drawing to render metafile into the bitmap.
Bitmap bmp = new Bitmap(bitmapwidth, bitmapheight);
Graphics graphics = Graphics.FromImage(bmp);
// graphics.FillRectangle(new System.Drawing.SolidBrush(System.Drawing.Color.White), 0, 0, bitmapwidth, bitmapheight);
graphics.DrawImage(metafile, 0, 0, bitmapwidth, bitmapheight);

return bmp.GetHbitmap();
}

// return a stream for the ExifUserComment in the given Gif
internal override Stream GetCommentFromGifStream(Stream stream)
{
// Read the GIF header ...
Bitmap img = new Bitmap(stream);
// Read the comment as that is where the ISF is stored...
// for reference the tag is PropertyTagExifUserComment [0x9286] or 37510 (int)
PropertyItem piComment = img.GetPropertyItem(37510);
return new MemoryStream(piComment.Value);
// Read the GIF header
Bitmap bitmap = new(stream);

// Read the comment as that is where the ISF is stored.
// For reference the tag is PropertyTagExifUserComment [0x9286] or 37510 (int)
PropertyItem? piComment = bitmap.GetPropertyItem(37510);
return new MemoryStream(piComment!.Value!);
}

// write a metafile stream to the output stream in PNG format
internal override void SaveMetafileToImageStream(MemoryStream metafileStream, Stream imageStream)
{
Metafile metafile = new Metafile(metafileStream);
Metafile metafile = new(metafileStream);
metafile.Save(imageStream, ImageFormat.Png);
}

// Get a bitmap from the given data (either BitmapSource or Bitmap)
private static Bitmap GetBitmapImpl(object data)
private static Bitmap? GetBitmapImpl(object? data)
{
BitmapSource bitmapSource = data as BitmapSource;
if (bitmapSource != null)
if (data is BitmapSource bitmapSource)
{
// Convert BitmapSource to System.Drawing.Bitmap to get Win32 HBITMAP.
BitmapEncoder bitmapEncoder;
Expand All @@ -152,23 +113,18 @@ private static Bitmap GetBitmapImpl(object data)
}
}

//returns bitmap snapshot of selected area
//this code takes a BitmapImage and converts it to a Bitmap so it can be put on the clipboard
internal override object GetBitmapFromBitmapSource(object source)
{
BitmapSource contentImage = (BitmapSource)source;
int imageWidth = (int)contentImage.Width;
int imageHeight = (int)contentImage.Height;

Bitmap bitmapFinal = new Bitmap(
imageWidth,
imageHeight,
System.Drawing.Imaging.PixelFormat.Format32bppRgb);
Bitmap bitmapFinal = new(imageWidth, imageHeight, PixelFormat.Format32bppRgb);

BitmapData bmData = bitmapFinal.LockBits(
new Rectangle(0, 0, imageWidth, imageHeight),
ImageLockMode.WriteOnly,
System.Drawing.Imaging.PixelFormat.Format32bppRgb);
new Rectangle(0, 0, imageWidth, imageHeight),
ImageLockMode.WriteOnly,
PixelFormat.Format32bppRgb);

FormatConvertedBitmap formatConverter = new FormatConvertedBitmap();
formatConverter.BeginInit();
Expand All @@ -177,10 +133,10 @@ internal override object GetBitmapFromBitmapSource(object source)
formatConverter.EndInit();

formatConverter.CopyPixels(
new Int32Rect(0, 0, imageWidth, imageHeight),
bmData.Scan0,
bmData.Stride * (bmData.Height - 1) + (bmData.Width * 4),
bmData.Stride);
new Int32Rect(0, 0, imageWidth, imageHeight),
bmData.Scan0,
bmData.Stride * (bmData.Height - 1) + (bmData.Width * 4),
bmData.Stride);

bitmapFinal.UnlockBits(bmData);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics.CodeAnalysis;

[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.Text")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.UnicodeText")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.Dib")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.Bitmap")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.EnhancedMetafile")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.CommaSeparatedValue")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.Dif")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.FileDrop")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.Html")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.Locale")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.MetafilePicture")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.OemText")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.Palette")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.PenData")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.Riff")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.Rtf")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.Serializable")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.StringFormat")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.SymbolicLink")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.Tiff")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.WaveAudio")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.Xaml")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataFormats.XamlPackage")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataObject.CopyingEvent")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataObject.PastingEvent")]
[assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Public API", Scope = "member", Target = "~F:System.Windows.DataObject.SettingDataEvent")]
[assembly: SuppressMessage("Usage", "CA2201:Do not raise reserved exception types", Justification = "Compat", Scope = "member", Target = "~M:System.Windows.Clipboard.IsCurrent(System.Windows.IDataObject)~System.Boolean")]
[assembly: SuppressMessage("Usage", "CA2201:Do not raise reserved exception types", Justification = "Compat", Scope = "member", Target = "~M:System.Windows.DataObject.System#Runtime#InteropServices#ComTypes#IDataObject#EnumFormatEtc(System.Runtime.InteropServices.ComTypes.DATADIR)~System.Runtime.InteropServices.ComTypes.IEnumFORMATETC")]
[assembly: SuppressMessage("Usage", "CA2201:Do not raise reserved exception types", Justification = "Compat", Scope = "member", Target = "~M:System.Windows.OleServicesContext.SetDispatcherThread")]
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

global using System;
global using System.Collections.Generic;
global using System.Diagnostics;

global using DataFormatsCore = System.Private.Windows.Ole.DataFormatsCore<
System.Windows.DataFormat>;

global using SR = MS.Internal.PresentationCore.SR;

global using DllImport = MS.Internal.PresentationCore.DllImport;
Loading