Skip to content

Commit bd74c4f

Browse files
JeremyKuhneLeafShi1
authored andcommitted
Tweak OLE code to allow metafile handling in WPF (dotnet#13045)
Few minor tweaks to handle metafile scenarios in WPF. Expand comments on IOleServices.
1 parent a567547 commit bd74c4f

File tree

10 files changed

+203
-167
lines changed

10 files changed

+203
-167
lines changed

src/System.Private.Windows.Core/src/System/Private/Windows/Ole/Composition.NativeToManagedAdapter.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,9 +258,8 @@ private static bool TryGetObjectFromDataObject<T>(
258258

259259
try
260260
{
261-
// Try to get the data as a bitmap first.
262-
if (request.Format == DataFormatNames.Bitmap
263-
&& TOleServices.TryGetBitmapFromDataObject(dataObject, out data))
261+
// Try to get platform specific data first.
262+
if (TOleServices.TryGetObjectFromDataObject(dataObject, request.Format, out data))
264263
{
265264
return true;
266265
}

src/System.Private.Windows.Core/src/System/Private/Windows/Ole/DataFormatNames.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ internal static partial class DataFormatNames
3434
internal const string FileNameAnsi = PInvokeCore.CFSTR_FILENAMEA;
3535
internal const string FileNameUnicode = PInvokeCore.CFSTR_FILENAME;
3636
internal const string BinaryFormatBitmap = "System.Drawing.Bitmap";
37+
internal const string BinaryFormatMetafile = "System.Drawing.Imaging.Metafile";
3738

3839
/// <summary>
3940
/// A format used internally by the drag image manager.
@@ -109,6 +110,12 @@ internal static void AddMappedFormats<T>(string format, T formats)
109110
case BinaryFormatBitmap:
110111
formats.Add(Bitmap);
111112
break;
113+
case Emf:
114+
formats.Add(BinaryFormatMetafile);
115+
break;
116+
case BinaryFormatMetafile:
117+
formats.Add(Emf);
118+
break;
112119
}
113120
}
114121

src/System.Private.Windows.Core/src/System/Private/Windows/Ole/DataStore.cs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,17 @@ public void SetData(Type format, object? data)
9494
SetData(format.FullName.OrThrowIfNull(), data);
9595
}
9696

97+
/// <inheritdoc cref="IDataObjectInternal.SetData(object?)"/>
98+
/// <remarks>
99+
/// <para>
100+
/// This is the only method that has special behavior for <see cref="ISerializable"/> objects.
101+
/// </para>
102+
/// </remarks>
97103
public void SetData(object? data)
98104
{
99105
ArgumentNullException.ThrowIfNull(data);
100106

101-
if (data is ISerializable
102-
&& !_mappedData.ContainsKey(DataFormatNames.Serializable))
107+
if (data is ISerializable && !_mappedData.ContainsKey(DataFormatNames.Serializable))
103108
{
104109
SetData(DataFormatNames.Serializable, data);
105110
}
@@ -120,20 +125,18 @@ public bool GetDataPresent(string format, bool autoConvert)
120125
{
121126
return _mappedData.ContainsKey(format);
122127
}
123-
else
124-
{
125-
string[] formats = GetFormats(autoConvert);
126128

127-
for (int i = 0; i < formats.Length; i++)
129+
string[] formats = GetFormats(autoConvert);
130+
131+
for (int i = 0; i < formats.Length; i++)
132+
{
133+
if (format.Equals(formats[i]))
128134
{
129-
if (format.Equals(formats[i]))
130-
{
131-
return true;
132-
}
135+
return true;
133136
}
134-
135-
return false;
136137
}
138+
139+
return false;
137140
}
138141

139142
public bool GetDataPresent(string format) => GetDataPresent(format, autoConvert: true);

src/System.Private.Windows.Core/src/System/Private/Windows/Ole/FormatEnumerator.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ public FormatEnumerator(IDataObjectInternal dataObject, Func<string, int> getFor
4343
dwAspect = ComTypes.DVASPECT.DVASPECT_CONTENT,
4444
ptd = 0,
4545
lindex = -1,
46-
tymed = format.Equals(DataFormatNames.Bitmap) ? ComTypes.TYMED.TYMED_GDI : ComTypes.TYMED.TYMED_HGLOBAL
46+
tymed = format == DataFormatNames.Bitmap
47+
? ComTypes.TYMED.TYMED_GDI
48+
: format == DataFormatNames.Emf ? ComTypes.TYMED.TYMED_ENHMF : ComTypes.TYMED.TYMED_HGLOBAL
4749
};
4850

4951
_formats.Add(temp);

src/System.Private.Windows.Core/src/System/Private/Windows/Ole/IOleServices.cs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55

66
namespace System.Private.Windows.Ole;
77

8+
/// <summary>
9+
/// Platform specific OLE services.
10+
/// </summary>
811
internal unsafe interface IOleServices
912
{
1013
/// <summary>
@@ -17,15 +20,29 @@ internal unsafe interface IOleServices
1720
/// <summary>
1821
/// Called after unsuccessfully performing clipboard <see cref="TYMED.TYMED_HGLOBAL"/> serialization.
1922
/// </summary>
23+
/// <remarks>
24+
/// <para>
25+
/// <paramref name="pformatetc"/> and <paramref name="pmedium"/> are checked for validity before this call.
26+
/// </para>
27+
/// </remarks>
28+
/// <param name="format">The data format that is being serialized.</param>
29+
/// <inheritdoc cref="IDataObject.GetDataHere(FORMATETC*, STGMEDIUM*)"/>
2030
static abstract HRESULT GetDataHere(string format, object data, FORMATETC* pformatetc, STGMEDIUM* pmedium);
2131

2232
/// <summary>
23-
/// If the <typeparamref name="T"/> is a bitmap this method will attempt to extract it
33+
/// If the <typeparamref name="T"/> is a the requested format this method will attempt to extract it
2434
/// from the <paramref name="dataObject"/>.
2535
/// </summary>
36+
/// <param name="format">The data format that is being requested.</param>
37+
/// <remarks>
38+
/// <para>
39+
/// This is intended for platform specific logic, notably for bitmaps and metafiles.
40+
/// </para>
41+
/// </remarks>
2642
/// <returns><see langword="true"/> if a bitmap was extracted.</returns>
27-
static abstract bool TryGetBitmapFromDataObject<T>(
43+
static abstract bool TryGetObjectFromDataObject<T>(
2844
IDataObject* dataObject,
45+
string format,
2946
[NotNullWhen(true)] out T data);
3047

3148
/// <summary>
@@ -46,6 +63,11 @@ static abstract bool TryGetBitmapFromDataObject<T>(
4663
/// <summary>
4764
/// Allows custom validation or adapting of <see cref="DataStore{TOleServices}"/> data and formats.
4865
/// </summary>
66+
/// <param name="format">
67+
/// The format to be checked against <paramref name="data"/>, can be modified to another format name if
68+
/// <paramref name="autoConvert"/> is true.
69+
/// </param>
70+
/// <param name="data">The data to be checked against <paramref name="data"/>.</param>
4971
static abstract void ValidateDataStoreData(ref string format, bool autoConvert, object? data);
5072

5173
/// <summary>

src/System.Private.Windows.Core/tests/System.Private.Windows.Core.Tests/System/Private/Windows/Ole/ClipboardCoreTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ private class InvalidThreadOleServices() : IOleServices
4242
static HRESULT IOleServices.OleFlushClipboard() => throw new NotImplementedException();
4343
static unsafe HRESULT IOleServices.OleGetClipboard(IDataObject** dataObject) => throw new NotImplementedException();
4444
static unsafe HRESULT IOleServices.OleSetClipboard(IDataObject* dataObject) => throw new NotImplementedException();
45-
static unsafe bool IOleServices.TryGetBitmapFromDataObject<T>(IDataObject* dataObject, [NotNullWhen(true)] out T data) => throw new NotImplementedException();
45+
static unsafe bool IOleServices.TryGetObjectFromDataObject<T>(IDataObject* dataObject, string requestedFormat, [NotNullWhen(true)] out T data) => throw new NotImplementedException();
4646
static void IOleServices.ValidateDataStoreData(ref string format, bool autoConvert, object? data) => throw new NotImplementedException();
4747
}
4848

src/System.Private.Windows.Core/tests/System.Private.Windows.Core.Tests/System/Private/Windows/Ole/MockOleServices.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ static void IOleServices.EnsureThreadState() { }
2121
static bool IOleServices.IsValidTypeForFormat(Type type, string format) => true;
2222
static void IOleServices.ValidateDataStoreData(ref string format, bool autoConvert, object? data) { }
2323

24-
static unsafe bool IOleServices.TryGetBitmapFromDataObject<T>(IDataObject* dataObject, [NotNullWhen(true)] out T data)
24+
static unsafe bool IOleServices.TryGetObjectFromDataObject<T>(IDataObject* dataObject, string requestedFormat, [NotNullWhen(true)] out T data)
2525
{
2626
data = default!;
2727
return false;

src/System.Windows.Forms/src/System/Windows/Forms/OLE/WinFormsOleServices.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,13 @@ static unsafe HRESULT IOleServices.GetDataHere(string format, object data, FORMA
5757
return HRESULT.DV_E_TYMED;
5858
}
5959

60-
static unsafe bool IOleServices.TryGetBitmapFromDataObject<T>(Com.IDataObject* dataObject, [NotNullWhen(true)] out T data)
60+
static unsafe bool IOleServices.TryGetObjectFromDataObject<T>(
61+
Com.IDataObject* dataObject,
62+
string requestedFormat,
63+
[NotNullWhen(true)] out T data)
6164
{
62-
if ((typeof(Bitmap) == typeof(T) || typeof(Image) == typeof(T))
65+
if (requestedFormat == DataFormatNames.Bitmap
66+
&& (typeof(Bitmap) == typeof(T) || typeof(Image) == typeof(T))
6367
&& TryGetBitmapData(dataObject, out Bitmap? bitmap))
6468
{
6569
data = (T)(object)bitmap!;

src/System.Windows.Forms/tests/TestUtilities/Data/DataObjectTestHelpers.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ public static TheoryData<string> UndefinedRestrictedFormat() =>
4242
DataFormats.Tiff,
4343
DataFormats.WaveAudio,
4444
DataFormats.SymbolicLink,
45-
DataFormats.EnhancedMetafile,
4645
DataFormats.MetafilePict,
4746
DataFormats.Palette
4847
];

0 commit comments

Comments
 (0)