|
10 | 10 | using System.Runtime.InteropServices;
|
11 | 11 | using System.Runtime.Serialization.Formatters.Binary;
|
12 | 12 | using Com = Windows.Win32.System.Com;
|
| 13 | +using Windows.Win32.System.Ole; |
13 | 14 | using ComTypes = System.Runtime.InteropServices.ComTypes;
|
14 | 15 |
|
15 | 16 | namespace System.Windows.Forms.Tests;
|
@@ -520,20 +521,14 @@ public unsafe void Clipboard_GetClipboard_ReturnsProxy()
|
520 | 521 | ((nint)dataUnknown.Value).Should().Be((nint)realDataPointerUnknown.Value);
|
521 | 522 | }
|
522 | 523 |
|
| 524 | + private class DerivedDataObject : DataObject { } |
| 525 | + |
523 | 526 | [WinFormsFact]
|
524 |
| - public void Clipboard_Set_DoesNotWrapTwice() |
| 527 | + public void Clipboard_SetDataObject_DerivedDataObject_ReturnsExpected() |
525 | 528 | {
|
526 |
| - string realDataObject = string.Empty; |
527 |
| - Clipboard.SetDataObject(realDataObject); |
528 |
| - |
529 |
| - IDataObject? clipboardDataObject = Clipboard.GetDataObject(); |
530 |
| - var dataObject = clipboardDataObject.Should().BeOfType<DataObject>().Which; |
531 |
| - dataObject.IsWrappedForClipboard.Should().BeTrue(); |
532 |
| - |
533 |
| - Clipboard.SetDataObject(clipboardDataObject!); |
534 |
| - IDataObject? clipboardDataObject2 = Clipboard.GetDataObject(); |
535 |
| - clipboardDataObject2.Should().NotBeNull(); |
536 |
| - clipboardDataObject2.Should().BeSameAs(clipboardDataObject); |
| 529 | + DerivedDataObject derived = new(); |
| 530 | + Clipboard.SetDataObject(derived); |
| 531 | + Clipboard.GetDataObject().Should().BeSameAs(derived); |
537 | 532 | }
|
538 | 533 |
|
539 | 534 | [WinFormsFact]
|
@@ -589,4 +584,119 @@ ComTypes.IEnumFORMATETC ComTypes.IDataObject.EnumFormatEtc(ComTypes.DATADIR dire
|
589 | 584 | void IDataObject.SetData(object? data) => throw new NotImplementedException();
|
590 | 585 | void ComTypes.IDataObject.SetData(ref ComTypes.FORMATETC formatIn, ref ComTypes.STGMEDIUM medium, bool release) => throw new NotImplementedException();
|
591 | 586 | }
|
| 587 | + |
| 588 | + [DllImport("user32.dll")] |
| 589 | + private static extern bool CloseClipboard(); |
| 590 | + |
| 591 | + [DllImport("user32.dll")] |
| 592 | + private static extern bool OpenClipboard(HWND hWndNewOwner); |
| 593 | + |
| 594 | + [DllImport("user32.dll")] |
| 595 | + private static extern bool SetClipboardData(uint uFormat, HANDLE data); |
| 596 | + |
| 597 | + [WinFormsFact] |
| 598 | + public unsafe void Clipboard_RawClipboard_SetClipboardData_ReturnsExpected() |
| 599 | + { |
| 600 | + OpenClipboard(HWND.Null).Should().BeTrue(); |
| 601 | + string testString = "test"; |
| 602 | + SetClipboardData((uint)CLIPBOARD_FORMAT.CF_UNICODETEXT, (HANDLE)Marshal.StringToHGlobalUni(testString)); |
| 603 | + CloseClipboard().Should().BeTrue(); |
| 604 | + |
| 605 | + DataObject dataObject = Clipboard.GetDataObject().Should().BeOfType<DataObject>().Which; |
| 606 | + dataObject.GetData(DataFormats.Text).Should().Be(testString); |
| 607 | + |
| 608 | + Clipboard.ContainsText().Should().BeTrue(); |
| 609 | + Clipboard.ContainsData(DataFormats.Text).Should().BeTrue(); |
| 610 | + Clipboard.ContainsData(DataFormats.UnicodeText).Should().BeTrue(); |
| 611 | + |
| 612 | + Clipboard.GetText().Should().Be(testString); |
| 613 | + Clipboard.GetText(TextDataFormat.Text).Should().Be(testString); |
| 614 | + Clipboard.GetText(TextDataFormat.UnicodeText).Should().Be(testString); |
| 615 | + |
| 616 | + Clipboard.GetData("System.String").Should().BeNull(); |
| 617 | + } |
| 618 | + |
| 619 | + [WinFormsFact] |
| 620 | + public void Clipboard_SetData_Text_Format_AllUpper() |
| 621 | + { |
| 622 | + // The fact that casing on input matters is likely incorrect, but behavior has been this way. |
| 623 | + Clipboard.SetData("TEXT", "Hello, World!"); |
| 624 | + Clipboard.ContainsText().Should().BeTrue(); |
| 625 | + Clipboard.ContainsData("TEXT").Should().BeTrue(); |
| 626 | + Clipboard.ContainsData(DataFormats.Text).Should().BeTrue(); |
| 627 | + Clipboard.ContainsData(DataFormats.UnicodeText).Should().BeTrue(); |
| 628 | + |
| 629 | + IDataObject dataObject = Clipboard.GetDataObject().Should().BeAssignableTo<IDataObject>().Subject; |
| 630 | + string[] formats = dataObject.GetFormats(); |
| 631 | + formats.Should().BeEquivalentTo(["System.String", "UnicodeText", "Text"]); |
| 632 | + |
| 633 | + formats = dataObject.GetFormats(autoConvert: false); |
| 634 | + formats.Should().BeEquivalentTo(["Text"]); |
| 635 | + |
| 636 | + // CLIPBRD_E_BAD_DATA returned when trying to get clipboard data. |
| 637 | + Clipboard.GetText().Should().BeEmpty(); |
| 638 | + Clipboard.GetText(TextDataFormat.Text).Should().BeEmpty(); |
| 639 | + Clipboard.GetText(TextDataFormat.UnicodeText).Should().BeEmpty(); |
| 640 | + |
| 641 | + Clipboard.GetData("System.String").Should().BeNull(); |
| 642 | + Clipboard.GetData("TEXT").Should().BeNull(); |
| 643 | + } |
| 644 | + |
| 645 | + [WinFormsFact] |
| 646 | + public void Clipboard_SetData_Text_Format_CanonicalCase() |
| 647 | + { |
| 648 | + string expected = "Hello, World!"; |
| 649 | + Clipboard.SetData("Text", expected); |
| 650 | + Clipboard.ContainsText().Should().BeTrue(); |
| 651 | + Clipboard.ContainsData("TEXT").Should().BeTrue(); |
| 652 | + Clipboard.ContainsData(DataFormats.Text).Should().BeTrue(); |
| 653 | + Clipboard.ContainsData(DataFormats.UnicodeText).Should().BeTrue(); |
| 654 | + |
| 655 | + IDataObject dataObject = Clipboard.GetDataObject().Should().BeAssignableTo<IDataObject>().Subject; |
| 656 | + string[] formats = dataObject.GetFormats(); |
| 657 | + formats.Should().BeEquivalentTo(["System.String", "UnicodeText", "Text"]); |
| 658 | + |
| 659 | + formats = dataObject.GetFormats(autoConvert: false); |
| 660 | + formats.Should().BeEquivalentTo(["System.String", "UnicodeText", "Text"]); |
| 661 | + |
| 662 | + Clipboard.GetText().Should().Be(expected); |
| 663 | + Clipboard.GetText(TextDataFormat.Text).Should().Be(expected); |
| 664 | + Clipboard.GetText(TextDataFormat.UnicodeText).Should().Be(expected); |
| 665 | + |
| 666 | + Clipboard.GetData("System.String").Should().Be(expected); |
| 667 | + |
| 668 | + // Case sensitivity matters so we end up reading stream/object from HGLOBAL instead of string. |
| 669 | + MemoryStream stream = Clipboard.GetData("TEXT").Should().BeOfType<MemoryStream>().Subject; |
| 670 | + byte[] array = stream.ToArray(); |
| 671 | + array.Should().BeEquivalentTo("Hello, World!\0"u8.ToArray()); |
| 672 | + } |
| 673 | + |
| 674 | + [WinFormsFact] |
| 675 | + public void Clipboard_SetDataObject_Text() |
| 676 | + { |
| 677 | + string expected = "Hello, World!"; |
| 678 | + Clipboard.SetDataObject(expected); |
| 679 | + Clipboard.ContainsText().Should().BeTrue(); |
| 680 | + Clipboard.ContainsData("TEXT").Should().BeTrue(); |
| 681 | + Clipboard.ContainsData(DataFormats.Text).Should().BeTrue(); |
| 682 | + Clipboard.ContainsData(DataFormats.UnicodeText).Should().BeTrue(); |
| 683 | + |
| 684 | + IDataObject dataObject = Clipboard.GetDataObject().Should().BeAssignableTo<IDataObject>().Subject; |
| 685 | + string[] formats = dataObject.GetFormats(); |
| 686 | + formats.Should().BeEquivalentTo(["System.String", "UnicodeText", "Text"]); |
| 687 | + |
| 688 | + formats = dataObject.GetFormats(autoConvert: false); |
| 689 | + formats.Should().BeEquivalentTo(["System.String", "UnicodeText", "Text"]); |
| 690 | + |
| 691 | + Clipboard.GetText().Should().Be(expected); |
| 692 | + Clipboard.GetText(TextDataFormat.Text).Should().Be(expected); |
| 693 | + Clipboard.GetText(TextDataFormat.UnicodeText).Should().Be(expected); |
| 694 | + |
| 695 | + Clipboard.GetData("System.String").Should().Be(expected); |
| 696 | + |
| 697 | + // Case sensitivity matters so we end up reading stream/object from HGLOBAL instead of string. |
| 698 | + MemoryStream stream = Clipboard.GetData("TEXT").Should().BeOfType<MemoryStream>().Subject; |
| 699 | + byte[] array = stream.ToArray(); |
| 700 | + array.Should().BeEquivalentTo("Hello, World!\0"u8.ToArray()); |
| 701 | + } |
592 | 702 | }
|
0 commit comments