Skip to content

Add shortCut copy paste In DemoConsole #13644

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Windows.Forms.Design.Behavior;
using System.Drawing;
using System.Drawing.Design;
using System.Collections;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms.Design.Behavior;

namespace System.Windows.Forms.Design;

Expand Down Expand Up @@ -52,6 +53,8 @@ internal partial class CommandSet : IDisposable
private StatusCommandUI _statusCommandUI; // Used to update the statusBar Information.
private readonly IUIService? _uiService;

private ICollection? _toBeCopiedComponents;

/// <summary>
/// Creates a new CommandSet object. This object implements the set
/// of commands that the UI.Win32 form designer offers.
Expand Down Expand Up @@ -421,6 +424,7 @@ internal static bool ExecuteSafely(Action action, bool throwOnException)

// This function will return true if call to func is successful, false otherwise
// Output of call to func is available in result out parameter
[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "retain this unused method")]
private static bool ExecuteSafely<T>(Func<T> func, bool throwOnException, [MaybeNullWhen(false)] out T result)
{
try
Expand Down Expand Up @@ -1397,29 +1401,8 @@ protected void OnMenuCopy(object? sender, EventArgs e)
{
Cursor.Current = Cursors.WaitCursor;

ICollection selectedComponents = GetCopySelection();

selectedComponents = PrependComponentNames(selectedComponents);

IDesignerSerializationService? ds = GetService<IDesignerSerializationService>();
Debug.Assert(ds is not null, "No designer serialization service -- we cannot copy to clipboard");
if (ds is not null)
{
object serializationData = ds.Serialize(selectedComponents);
using MemoryStream stream = new();
#pragma warning disable SYSLIB0011 // Type or member is obsolete
new BinaryFormatter().Serialize(stream, serializationData);
#pragma warning restore SYSLIB0011
stream.Seek(0, SeekOrigin.Begin);
byte[] bytes = stream.GetBuffer();
IDataObject dataObj = new DataObject(CF_DESIGNER, bytes);
if (!ExecuteSafely(() => Clipboard.SetDataObject(dataObj), throwOnException: false))
{
_uiService?.ShowError(SR.ClipboardError);
}
}

UpdateClipboardItems(null, null);
_toBeCopiedComponents = SelectionService!.GetSelectedComponents();
_commandSet.First(command => command.CommandID == StandardCommands.Paste)?.UpdateStatus();
}
finally
{
Expand Down Expand Up @@ -1843,52 +1826,31 @@ protected void OnMenuPaste(object? sender, EventArgs e)
return;
}

bool clipboardOperationSuccessful = ExecuteSafely(Clipboard.GetDataObject, false, out IDataObject? dataObj);

if (clipboardOperationSuccessful)
if (_toBeCopiedComponents is not null && _toBeCopiedComponents.Count != 0)
{
ICollection? components = null;
List<IComponent>? components = null;
bool createdItems = false;

// Get the current number of controls in the Component Tray in the target
ComponentTray? tray = GetService<ComponentTray>();
int numberOfOriginalTrayControls = tray is not null ? tray.Controls.Count : 0;

// We understand two things: CF_DESIGNER, and toolbox items.
object? data = dataObj?.GetData(CF_DESIGNER);

using DesignerTransaction trans = host.CreateTransaction(SR.CommandSetPaste);
if (data is byte[] bytes)
{
MemoryStream s = new(bytes);

// CF_DESIGNER was put on the clipboard by us using the designer serialization service.
if (TryGetService(out IDesignerSerializationService? ds))
{
s.Seek(0, SeekOrigin.Begin);
#pragma warning disable SYSLIB0011 // Type or member is obsolete
#pragma warning disable CA2300 // Do not use insecure deserializer BinaryFormatter
object serializationData = new BinaryFormatter().Deserialize(s); // CodeQL[SM03722, SM04191] : The operation is essential for the design experience when users are running their own designers they have created. This cannot be achieved without BinaryFormatter
#pragma warning restore CA2300
#pragma warning restore SYSLIB0011
using (ScaleHelper.EnterDpiAwarenessScope(DPI_AWARENESS_CONTEXT.DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))
{
components = ds.Deserialize(serializationData);
}
}
}
else if (TryGetService(out IToolboxService? ts) && ts.IsSupported(dataObj, host))
components = DesignerUtils.CopyDragObjects(new ReadOnlyCollection<IComponent>([.. _toBeCopiedComponents.Cast<IComponent>()]), GetService<IDesignerHost>()!);

if (components is not null && _toBeCopiedComponents.Count == components.Count)
{
// Now check for a toolbox item.
ToolboxItem? ti = ts.DeserializeToolboxItem(dataObj, host);
if (ti is not null)
int i = 0;
foreach (IComponent component in _toBeCopiedComponents)
{
using (ScaleHelper.EnterDpiAwarenessScope(DPI_AWARENESS_CONTEXT.DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))
if (component is Control original && components[i] is Control duplicate)
{
components = ti.CreateComponents(host);
duplicate.Parent = original.Parent;
duplicate.Location = new Point(original.Location.X + 15, original.Location.Y + 15);
}

createdItems = true;
i++;
}
}

Expand All @@ -1897,7 +1859,7 @@ protected void OnMenuPaste(object? sender, EventArgs e)
if (components is not null && components.Count > 0)
{
// Make copy of Items in Array..
object[] allComponents = new object[components.Count];
IComponent[] allComponents = new IComponent[components.Count];
components.CopyTo(allComponents, 0);

List<IComponent> selectComps = [];
Expand Down Expand Up @@ -2170,12 +2132,9 @@ protected void OnMenuPaste(object? sender, EventArgs e)
}

trans.Commit();
SelectionService?.SetSelectedComponents(components);
}
}
else
{
_uiService?.ShowError(SR.ClipboardError);
}
}
finally
{
Expand Down Expand Up @@ -3091,28 +3050,7 @@ protected void OnStatusPaste(object? sender, EventArgs e)
}
}

// Not being inherited. Now look at the contents of the data
bool clipboardOperationSuccessful = ExecuteSafely(Clipboard.GetDataObject, false, out IDataObject? dataObj);

bool enable = false;

if (clipboardOperationSuccessful && dataObj is not null)
{
if (dataObj.GetDataPresent(CF_DESIGNER))
{
enable = true;
}
else
{
// Not ours, check to see if the toolbox service understands this
if (TryGetService(out IToolboxService? ts))
{
enable = host is not null ? ts.IsSupported(dataObj, host) : ts.IsToolboxItem(dataObj);
}
}
}

cmd.Enabled = enable;
cmd.Enabled = _toBeCopiedComponents is not null;
Copy link
Preview

Copilot AI Jun 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This enables the Paste command even when there are no components to paste. Change the check to _toBeCopiedComponents?.Count > 0 so the command is only enabled when items are available.

Suggested change
cmd.Enabled = _toBeCopiedComponents is not null;
cmd.Enabled = _toBeCopiedComponents?.Count > 0;

Copilot uses AI. Check for mistakes.

}

private void OnStatusPrimarySelection(object? sender, EventArgs e)
Expand Down