简体   繁体   中英

Set same icon for all my Forms

Is there any way to set the same icon to all my forms without having to change one by one? Something like when you setup GlobalAssemblyInfo for all your projects inside your solution.

  1. In the project properties > Application > Icon and Manifest > browse for a *.ico file and add it there.

  2. In the constructor or _Load event of a Form, simply add:

     this.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);

One option would be to inherit from a common base-Form that sets the Icon in the constructor (presumably from a resx). Another option might be PostSharp - it seems like it should be possible to do this (set .Icon) via AOP; not trivial, though. Finally, you could use a simple utility method (perhaps an extension method) to do the same.

Best of all, with the first option, you could probably risk a Ctrl + H (replace all) from : Form or : System.Windows.Forms.Form to : MyCustomForm .

In additional to Marc's recommendation, you may want your forms to automatically inherit the icon of the executing assembly that contains/calls them.
This can be done by adding the following code to your inherited form:

public MyCustomForm()
{
    Icon = GetExecutableIcon();
}

public Icon GetExecutableIcon()
{
    IntPtr large;
    IntPtr small;
    ExtractIconEx(Application.ExecutablePath, 0, out large, out small, 1);
    return Icon.FromHandle(small);
}

[DllImport("Shell32")]
public static extern int ExtractIconEx(
    string sFile,
    int iIndex,
    out IntPtr piLargeVersion,
    out IntPtr piSmallVersion,
    int amountIcons);

This is the way to set the same icon to all forms without having to change one by one. This is what I coded in my applications.

FormUtils.SetDefaultIcon();

Here a full example ready to use.

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        //Here it is.
        FormUtils.SetDefaultIcon();

        Application.Run(new Form());
    }
}

Here is the class FormUtils:

using System.Drawing;
using System.Windows.Forms;

public static class FormUtils
{
    public static void SetDefaultIcon()
    {
        var icon = Icon.ExtractAssociatedIcon(EntryAssemblyInfo.ExecutablePath);
        typeof(Form)
            .GetField("defaultIcon", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)
            .SetValue(null, icon);
    }
}

And here the class EntryAssemblyInfo. This is truncated for this example. It is my custom coded class taken from System.Winforms.Application.

using System.Security;
using System.Security.Permissions;
using System.Reflection;
using System.Diagnostics;

public static class EntryAssemblyInfo
{
    private static string _executablePath;

    public static string ExecutablePath
    {
        get
        {
            if (_executablePath == null)
            {
                PermissionSet permissionSets = new PermissionSet(PermissionState.None);
                permissionSets.AddPermission(new FileIOPermission(PermissionState.Unrestricted));
                permissionSets.AddPermission(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode));
                permissionSets.Assert();

                string uriString = null;
                var entryAssembly = Assembly.GetEntryAssembly();

                if (entryAssembly == null)
                    uriString = Process.GetCurrentProcess().MainModule.FileName;
                else
                    uriString = entryAssembly.CodeBase;

                PermissionSet.RevertAssert();

                if (string.IsNullOrWhiteSpace(uriString))
                    throw new Exception("Can not Get EntryAssembly or Process MainModule FileName");
                else
                {
                    var uri = new Uri(uriString);
                    if (uri.IsFile)
                        _executablePath = string.Concat(uri.LocalPath, Uri.UnescapeDataString(uri.Fragment));
                    else
                        _executablePath = uri.ToString();
                }
            }

            return _executablePath;
        }
    }
}

I wasn't sure if I wanted to use inheritance here, so I used an extension method:

public static class MyExtensionMethods
{
    public static void SetAppIcon(this Form form)
    {
        form.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
    }
}

Then in any form's constructor:

this.SetAppIcon();

Note: this will cause a crash if you try to run the application from a network location

It is an old question, but this method worked for me to get the same icon in all forms without having to add it in every form's properties.

First I added a new icon in the 'Resources' node under 'Properties' (add resource => New Icon).

By default some icon is created and stored in your resources location (look for the 'Filename' property on the icon).

Assuming you have a .ico file ready, you can copy it to that folder.

Delete the one Visual Studio created in that folder and rename your own to the exact same name.

Visual Studio will prompt you if you want to reload the resource since it was modified. (click 'Yes')

That way you have your Logo available under resources.

Now I have made a general method to change the form title to my default and set the form icon and call that in every form right after InitializeComponent();

How that looks in the form cs (m is the class that holds the general method):

m.set_form_defaults(this, "Title here");

And this is the method itself:

    public void set_form_defaults(Form frm,string frmTitle)
    {

        frm.Icon = ((System.Drawing.Icon)(Properties.Resources.Logo_V2));
        frm.Text = frmTitle + " " + show_current_server();

    }

Of course you don't need to add the form title here, but that is just because I want to show some stored properties to the user (current server)

Alternative to setting in the constructor is overriding the Owner property, and taking the icon of the owner form.

public new Form Owner {
    set {
        this.Icon = (value == null ? null : value.Icon);
        base.Owner = value;
    }

    get {
        return base.Owner;
    }
}

I'm not sure if the MS VS designer can deal with Forms that don't derive directly from Form. If not then you may try to copy the main form's icon to all other forms: for each form in Forms collection

form.icon = MainFrom.Icon

Or perhaps in each Form's _Loaded event:

Icon = MainFrom.Icon

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM