Bling For Dialog - Is there an Easier way to add an Icon to an Eto Dialog?

I am using VS-C# and have created an embedded resource for images and Icons. I am able to get the icon to display in the dialog but I was wondering if my approach can be improved. I have been:

  • Using resource manager to pull the icon out of the resource
  • Using a method to convert from Icon to memory stream
  • Using Eto.Drawing.Icon to convert the memory stream to a Eto Icon
  • Then using this result as the Icon for the dialog

Does Eto have a method that will do this internally with out going through this conversion?

Any help would be appreciated:

Best;

Steve

ps: tried this but it does not connected to an embedded resource for me:

dlg.Icon = Icon.FromRecource("Heart.ico")

The Dialog:

  internal class MainDialog : Dialog
    {
        public string Selected { private set; get; }

        public MainDialog()
        {
            DisplayMode = DialogDisplayMode.Attached;
            Resizable = true;
            Padding = 3;
        }
        public void ListBoxDialog()
        {
            ListBox listBox = new ListBox()
            {
                ID = "lbListBox"
            };
            listBox.SelectedKeyChanged += (sender, args) => ListBox_OnClkick(sender, args);

            var layout = new DynamicLayout
            {
                ID = "ListBoxLayout",
            };
            layout.AddRow(new TableLayout()
            {
                Style = "table-layout-style",
                Rows =
                    {
                        new TableRow(listBox) {ScaleHeight = false}
                    }
            }
            );

            Content = new Scrollable();
            Content = layout;
        }

        private void ListBox_OnClkick(object sender, EventArgs args)
        {
            ListBox lb = (ListBox) sender;
            Selected = lb.SelectedValue.ToString();
            Close();
        }
    }

The Implementation:

using (MainDialog mainDialog = new View.MainDialog())
	{
///It seams you need to create an Eto Icon from a memory stream
///Does Eto have a method to go from System.Drawing.Icon to Eto.Drawing.Icon?
		MemoryStream memoryStream = new MemoryStream();
		memoryStream = Singleton.IconToStream((System.Drawing.Icon) Resources.ResourceManager.GetObject("SimpleListIcon"));
		Eto.Drawing.Icon etoIcon = new Eto.Drawing.Icon(memoryStream);

		mainDialog.Icon = etoIcon;
		mainDialog.Size = new Size(300, 500);
		mainDialog.Title = "Page Size";
		mainDialog.ListBoxDialog();
		ListBox lb = (ListBox)mainDialog.Children.First(i => i.ID == "lbListBox");
		lb.DataStore = documentList;
		mainDialog.Visible = true;
		mainDialog.ShowModal();
		if (mainDialog.Selected == null)
		{
			_msg = $"Page size was not selected.";
			_note = new SlException(Level.Information, 383, _msg);
			break;
		}
		_docString.SlPageViewSize = mainDialog.Selected;
		_docString.SlPageView = pageViewString;
		_msg = $"Page view {pageViewString} with a size of '{slPageViewSizeString}' will be created.";
		_note = new SlException(Level.Information, 389, _msg);
		break;
	}

System.Drawing.Icon to Memory stream:

        public static MemoryStream IconToStream(System.Drawing.Icon icon)
        {
            MemoryStream memoryStream = new MemoryStream();
            icon.Save(memoryStream);
            return memoryStream;
        }

Hi @slyon,

For using a System.Drawing.Icon, we recommend using the DrawingUtilities.LoadIconWithScaleDown method found in the Rhino.UI namespace.

For example:

using Rhino.UI;
using System.Drawing;

var res = "MyTestPlugIn.Resources.MyIcon.ico";
var size = 32;
var icon = DrawingUtilities.LoadIconWithScaleDown(res, size, GetType().Assembly);

If you need an Eto.Drawing.Icon, just use it’s Icon.FromResource static function:

using Eto.Drawing

var res = "MyTestPlugIn.Resources.MyIcon.ico";
var icon = Icon.FromResource(res, size, GetType().Assembly);

A more modern approach for displaying images in forms is to ditch the old-school Windows icons and use embedded .png files. Unlike WinForms, Eto is isn’t pixel based. So it’s better to save a series of .png files that are of the size you want to show in for form. In this way, the size of the image control the layout of the form, not some arbitrary, hard-coded pixel value.

Also, you can embed serveral sizes of a .png file and Eto will choose the correct one automatically based on the DPI scale of the system.

For example, let’s say you want to show some image for each item in a list. On a standard Windows system, these image are usually 16x16 pixel, so you’d add the following files as embedded resources:

MyImage.png
MyImage@2x.png 
MyImage@3x.png
MyImage@4x.png
// etc.

each @<something>x file is just the same image but at a larger scale. Thus MyImage@2x.png would be 32x32, MyImage@3x.png would be 48x48, etc.

All you have to do to load this “icon” like this:

using Eto.Drawing

var res = "MyTestPlugIn.Resources.MyImage.png";
var icon = Icon.FromResource(res, size, GetType().Assembly);

Hope this helps.

– Dale

3 Likes

Dale @dale:

Going png bling, very cool, and yes this help a lot!

Best;

Steve

Trying to get this going today and in trying out:

Assembly asy = typeof(BuildController).Assembly;
System.Drawing.Icon icon3 =  Rhino.UI.DrawingUtilities.LoadIconWithScaleDown("MyAssy.Properties.Resources.ListIcon", 32, asy);

Or

Assembly asy = typeof(BuildController).Assembly;
System.Drawing.Icon icon3 =  Rhino.UI.DrawingUtilities.LoadIconWithScaleDown("ListIcon", 32, asy);

And many other syntax tries, they all return null. Any Ideas or is there a Rhino.UI embedded resource that I am not aware of?

If I am on the right track, I think I just need a little more info about the Name parameter of Rhino.UI.DrawingUtilities.LoadIconWithScaleDown . The API says it is the
" resourceName
Type: System.String
The case-sensitive name of the icon manifest resource being requested."

Just to let you know, I know the embedded resource is there because this is working:

Assembly asy = typeof(BuildController).Assembly;

///public static class EtoExtensions
System.Drawing.Icon icon1 = Resources.ListIcon;
Eto.Drawing.Icon icon2 = icon1.ToEto();

Thanks for any help!

Best;

Steve

The following is stuff from the resource class created in the assembly so you can see where I am getting the name from.

 [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
        internal static global::System.Resources.ResourceManager ResourceManager {
            get {
                if (object.ReferenceEquals(resourceMan, null)) {
                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MyAssy.Properties.Resources", typeof(Resources).Assembly);
                    resourceMan = temp;
                }
                return resourceMan;
            }
        }
internal static System.Drawing.Icon ListIcon {
            get {
                object obj = ResourceManager.GetObject("ListIcon", resourceCulture);
                return ((System.Drawing.Icon)(obj));
            }
        }

Hi @slyon,

Try out my blingy sample and let me know if you have any questions.

TestSlyon.zip (101.1 KB)

– Dale

1 Like

@dale

Dale;

Just figured it out! I was using the wrong embedded resources. Sorry for the question and thank you for following up with the code. I will take a look at it tomorrow.

Best;

Steve

@dale

Dale:

I was playing around with this a bit this morning and was looking at some of the other Options Eto had and came up with the following code.

This all works except setting the Icon for the Dialog. It defaults to the Rhino Icon. I know it is the long way around but building the Icon for the window like this should work?

Anyway, thought you should know. Give me a shout if I am looking at this the wrong way or want the code. I don’t want my bling to get out of control! By the way, I had to brand the kitties to really see how this was sizing them. Again, thanks a bunch for the code. Really helped.

      Eto.Drawing.IconFrame iconFrame0 = new IconFrame(1, Eto.Drawing.Bitmap.FromResource("TestSlyon.Resources.Cat-clean@2x.png"));
      Eto.Drawing.IconFrame iconFrame1 = new IconFrame(1, Eto.Drawing.Bitmap.FromResource("TestSlyon.Resources.Cat-clean@3x.png"));
      Eto.Drawing.IconFrame iconFrame2 = new IconFrame(1, Eto.Drawing.Bitmap.FromResource("TestSlyon.Resources.Cat-clean@4x.png"));
      Eto.Drawing.IconFrame[] iconFrames = new Eto.Drawing.IconFrame[3];
      iconFrames[0] = iconFrame0;
      iconFrames[1] = iconFrame1;
      iconFrames[2] = iconFrame2;
      Eto.Drawing.Icon icon = new Icon(iconFrames);
      var Image_01 = new Eto.Forms.ImageView
      {
          Image = icon,
          Size = new Size(20,20)
      };

      var Image_02 = new Eto.Forms.ImageView
      {
          Image = icon,
          Size = new Size(65,65)
      };

      var Image_03 = new Eto.Forms.ImageView
      {
          Image = icon,
          Size = new Size(80,80)
      };

      //
      // Summary:
      //     Gets or sets the icon for the window to show in the menu bar.
      //
      // Value:
      //     The icon for this window.
      //
      // Remarks:
      //     The icon should have many variations, such as 16x16, 24x24, 32x32, 48x48, 64x64,
      //     etc. This ensures that the many places it is used (title bar, task bar, switch
      //     window, etc) all have optimized icon sizes. For OS X, the application icon is
      //     specified in the .app bundle, not by this value.

      //Does not work, defaults to Rhino icon.
      Icon = icon;

      //This works, scales icon down
      System.Drawing.Icon icon1 =  Rhino.UI.DrawingUtilities.LoadIconWithScaleDown("TestSlyon.Resources.Cat-sleep.ico", 32);
      Icon = icon1.ToEto();

Try setting the dialog icon in the OnLoadComplete override:

protected override void OnLoadComplete(EventArgs e)
{
  base.OnLoadComplete(e);
  this.RestorePosition();

  System.Drawing.Icon sleep_icon = Rhino.UI.DrawingUtilities.LoadIconWithScaleDown("TestSlyon.Resources.Cat-sleep.ico", 32);
  this.Icon = PlatformServiceProvider.Service.ToEtoIcon(sleep_icon.Handle);
}

– Dale

Dale, Steve,

this was very helpful. Thanks for putting togehter the example. The *.ico works perfect. I couldn’t get the png to load.

kindest
Christian