Single use of ICON in all forms

  • Thread starter Thread starter Ken Allen
  • Start date Start date
K

Ken Allen

I am developing a C#/.Net app that contains a significant number of forms
(about 32). In testing to date the size of the debug EXE is about 400 KB
and the size of the release EXE is about 325 -- cool.

A friend developed a neat icon file (all sizes and masks) for use by the
app. I replaced the generic App.ico file with the new one, opened the
solution and built it and, presto, a new icon for the program! But the size
went up a bit since his file is 27 KB and the generic icon file was only
1KB.

I then went to every form and, in the designer, set the icon property of
each form to point to this file -- that bloated the size of the EXE to over
1MB in debug and 930KB in release!

Since this icon file is already part of the project, how can I have all of
the forms use this icon without all of them bloating their .resx files?

-ken
 
Didn't try on 32 forms but should work:
Define the form's icons at run time, eg in form_load:

Me.Icon = New Icon("E:\Icons\Folder.ico")

This may cause a very slight runtime overhead, but the icon copies stay out
of the resource file. You may want to use relative file spec (relative to
the exe).

Hope this works
Paul
 
Hello Paul,

Even better would be to read it from a resource stream. Embed the icon into your program as an embedded resource, and reference it like this:

class Images
{
private Images() { }

public static Image AppIcon { get { return GetImage("app.ico"); } }

private static Image GetImage(string name)
{
Stream strm = Assembly.GetExecutingAssembly().GetManifestResourceStream(typeof(Images), name);
return Image.FromStream(strm);
}
}

In code then:

this.Icon = Images.AppIcon;
 
Interesting. Given that the icon is already part of the assembly and is used
(at design time) as the assembly icon, can I access that directly? Embedding
it as a resource would still leave me with two (2) copies -- the embedded
resource and the included image file.

How do I go about embedding the image as a resource anyway? I have not
needed to do this to date, but have read enough to have become completely
confused by the mechanisms and namespace issues -- I keep reading about
people having problems because thay did not use the proper naming resolution
to reach the resources. I do seem that the .Net resource files are
completely different from old VS6 resource files, and most of the
improvements are welcome, but the mechanisms for accessing the contents seem
more complex than they need to be.

-ken

Matt Berther said:
Hello Paul,

Even better would be to read it from a resource stream. Embed the icon
into your program as an embedded resource, and reference it like this:
 
Hello Ken,

Using this technique, you wouldnt have 2 copies, because you would go through and remove all the design time icons...

Embedding the file as a resource is no big deal... Select Embedded Resource as the build action from the file's properties in VS.NET. Reading it is not too difficult once you get the basics...

1. Your project's default namespace is used as the base.
2. Any folders that your file is located in are added to the namespace.

So... Assuming a project with a default namespace of MyName.MyProject and a file named app.ico in a folder called ResourceItems, the string to get the file would be:

MyName.MyProject.ResourceItems.app.ico
 
OK, so I set the build action on the ICON file as indicated. I then entered
the following two lines of code in the constructor for my form:

Stream strm =
Assembly.GetExecutingAssembly().GetManifestResourceStream(typeof(Image),
"TestIcons.TestIcons.App.ico");
this.Icon = Image.FromStream(strm);

Where "TestIcons" is the name of the solution and the project. When I
attempt to compile, I get the following error:

Cannot implicitly convert type 'System.Drawing.Image' to
'System.Drawing.Icon'

It is odd that I am loading an "Image" resource when it is really an "Icon",
but the Icon class does not have a FromStream() method. An explict cast of
the Image to an Icon also fails.

What am I doing wrong?

-ken

Matt Berther said:
Hello Ken,

Using this technique, you wouldnt have 2 copies, because you would go
through and remove all the design time icons...
Embedding the file as a resource is no big deal... Select Embedded
Resource as the build action from the file's properties in VS.NET. Reading
it is not too difficult once you get the basics...
1. Your project's default namespace is used as the base.
2. Any folders that your file is located in are added to the namespace.

So... Assuming a project with a default namespace of MyName.MyProject and
a file named app.ico in a folder called ResourceItems, the string to get the
file would be:
 
I have changed the code again to the following.

string[] names = Assembly.GetExecutingAssembly().GetManifestResourceNames();
MessageBox.Show("The first resource name is '" + names[0] + "'.");
Stream strm =
Assembly.GetExecutingAssembly().GetManifestResourceStream(typeof(Image),
names[0]);
if (strm != null)
{
Image icon = Image.FromStream(strm);
}
else
{
MessageBox.Show("Did not load resource!");
}

The name of the first resource is "IconTest.App.ico", but the 'strm'
variable is not being set to a stream value -- it remains null.

I get the same result if I change the type from Image to Icon when
attempting to open the manifest resource string!

-ken


Matt Berther said:
Hello Ken,

Using this technique, you wouldnt have 2 copies, because you would go
through and remove all the design time icons...
Embedding the file as a resource is no big deal... Select Embedded
Resource as the build action from the file's properties in VS.NET. Reading
it is not too difficult once you get the basics...
1. Your project's default namespace is used as the base.
2. Any folders that your file is located in are added to the namespace.

So... Assuming a project with a default namespace of MyName.MyProject and
a file named app.ico in a folder called ResourceItems, the string to get the
file would be:
 
Hello Ken,

For what you're doing, try this:

Stream strm = Assembly.GetExecutingAssembly().GetManifestResourceStream("TestIcons.App.ico");
this.Icon = new Icon(strm);
 
OK, I got a variation of this to work. Unfortunately the code as you wrote
it throws an exception on the assignment to this.Icon, but if I assign the
new Icon to a local variable and then assign that to the form Icon property
then it works properly!

Thanks.

-ken
 
Hello Ken,

That makes no sense... YOu're saying that this works:

Assembly.GetExecutingAssembly().GetManifestResourceStream("TestIcons.App.ico ");
Icon ico = new Icon(strm);

this.Icon = ico;

What was the original exception?
 
No, it did not make any sense, and I cannot reproduce it now. At the time is
was reporting that it could not perform a conversion from an image into an
icon, but a relaunch of the developer studio no longer produces this. I have
seen this from time to time before as well, where the compiler did not like
the direct assignment but was happy when I saved it in a vaiable first!
Other times it does not complain and I can change the code back to direct
assignment. It must be some temporal disturbance!

-ken
 
Back
Top