| File: System\ComponentModel\Design\BinaryEditor.cs | Web Access |
| Project: src\winforms\src\System.Windows.Forms.Design\src\System.Windows.Forms.Design.csproj (System.Windows.Forms.Design) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Drawing.Design; using System.Text; using System.Windows.Forms; using System.Windows.Forms.Design; namespace System.ComponentModel.Design; /// <summary> /// Generic editor for editing binary data. This presents a hex editing window to the user. /// </summary> public sealed partial class BinaryEditor : UITypeEditor { private const string HELP_KEYWORD = "System.ComponentModel.Design.BinaryEditor"; private ITypeDescriptorContext? _context; private BinaryUI? _binaryUI; internal object? GetService(Type serviceType) { if (_context is null) { return null; } return _context.TryGetService(out IDesignerHost? designerhost) ? designerhost.GetService(serviceType) : _context.GetService(serviceType); } private bool TryGetService<T>([NotNullWhen(true)] out T? service) where T : class { service = GetService(typeof(T)) as T; return service is not null; } /// <summary> /// Converts the given object to an array of bytes to be manipulated by the editor. The default implementation /// of this supports byte[] and <see cref="Stream"/> objects. /// </summary> internal static byte[] ConvertToBytes(object value) { if (value is Stream stream) { stream.Position = 0; int byteCount = (int)(stream.Length - stream.Position); byte[] bytes = new byte[byteCount]; stream.ReadExactly(bytes, 0, byteCount); return bytes; } if (value is byte[] byteArray) { return byteArray; } if (value is string stringValue) { int size = stringValue.Length * 2; byte[] buffer = new byte[size]; Encoding.Unicode.GetBytes(stringValue.AsSpan(), buffer.AsSpan()); return buffer; } Debug.Fail($"No conversion from {value?.GetType().FullName ?? "null"} to byte[]"); return null; } /// <summary> /// Converts the given byte array back into a native object. If the object itself needs to be replaced (as is /// the case for arrays), then a new object may be assigned out through <paramref name="value"/>. /// </summary> internal static void ConvertToValue(byte[] bytes, ref object value) { if (value is Stream stream) { stream.Position = 0; stream.Write(bytes, 0, bytes.Length); } else if (value is byte[]) { value = bytes; } else if (value is string) { value = BitConverter.ToString(bytes); } else { Debug.Fail($"No conversion from byte[] to {value?.GetType().FullName ?? "null"}"); } } public override object? EditValue(ITypeDescriptorContext? context, IServiceProvider provider, object? value) { if (provider is null) { return value; } _context = context; if (!provider.TryGetService(out IWindowsFormsEditorService? editorService)) { return value; } // Child modal dialog- launching in SystemAware mode. _binaryUI ??= ScaleHelper.InvokeInSystemAwareContext(() => new BinaryUI(this)); _binaryUI.Value = value; if (editorService.ShowDialog(_binaryUI) == DialogResult.OK) { value = _binaryUI.Value; } _binaryUI.Value = null; return value; } /// <inheritdoc /> public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext? context) => UITypeEditorEditStyle.Modal; internal void ShowHelp() { if (TryGetService(out IHelpService? helpService)) { helpService.ShowHelpFromKeyword(HELP_KEYWORD); } else { Debug.Fail("Unable to get IHelpService."); } } }