在运行时将更改应用于主窗体的Form.Icon

9

我有一个System.Windows.Forms.Form,并希望在运行时更改Form.Icon以显示状态。我已成功从项目资源中加载了图标:

Type type = this.GetType();
System.Resources.ResourceManager resources =
    new System.Resources.ResourceManager(type.Namespace + ".Properties.Resources", this.GetType().Assembly);
this.Icon = (System.Drawing.Icon)resources.GetObject(
    type.Namespace + ".Icons." + statusText + ".ico");

但是显示的图标始终保持不变(设计时图标)。我需要调用一个方法告诉表单应用更改吗?我的Form.Icon使用有什么问题吗?

5个回答

15

我不明白为什么你要这么麻烦地做这件事。只需将图标添加到资源中。 项目 + 属性,资源选项卡,单击“添加资源”按钮上的箭头,选择“添加现有文件”。然后在运行时可以像这样使用:

    private void button1_Click(object sender, EventArgs e) {
        this.Icon = Properties.Resources.Mumble;
    }

其中Mumble是图标的名称。

如果您百分之百确定GetObject()不会返回null,则尝试在设计器中设置Icon属性。如果仍未显示,则图标格式可能存在问题。确保它没有太多的颜色,在XP上256个颜色可行。


嗨,汉斯,上面的代码存在类型转换问题(位图无法转换为图标类型,我猜测)。对此很抱歉。 - Siva Gopal
1
@Siva,Hans的示例对我而言不需要转换。也许您还没有将资源添加为图标? - Hinek
谢谢,我得到了一个状态文本(字符串),并将图标放在我的资源中。我想通过状态文本加载它们(以便灵活添加另一个状态和图标)。您的方法有效,但不够灵活...所以当加载资源时,我必须检查我做错了什么... - Hinek
1
@Hans 至少有两个原因要这样做“艰难的方式”:(1)在多个图标之间切换和(2)对设计师的反感(我的最爱)。 - Bitterblue

5

好的,Siva和Hans是对的:GetObject返回null,因为资源的名称不正确。通过以下更改,它可以正常工作:

Type type = this.GetType(); 
System.Resources.ResourceManager resources = 
new System.Resources.ResourceManager(type.Namespace + ".Properties.Resources", this.GetType().Assembly);

// here it comes, call GetObject just with the resource name, no namespace and no extension
this.Icon = (System.Drawing.Icon)resources.GetObject(statusText); 

感谢您的所有帮助。

实际上,你正在使用命名空间,但在 ".Properties.Resources" 之前需要的是类名。 - Engineer

3
我猜首先,你的GetObject(...)返回了null。这就是类型转换无声地结束而不抛出错误或更改图标的原因。
如果可能的话,可以使用:
this.Icon = new System.Drawing.Icon(...) 

重载,然后尝试。


好的,没关系,现在我明白了:我从另一个示例中复制了整个名称空间之类的东西,这让GetObject()返回null... 这样做就可以了:this.Icon = (System.Drawing.Icon)resources.GetObject(statusText); - Hinek

1

是的,每当您的应用程序状态发生变化时,您都必须更改图标。

我使用一个简单的WinForm应用程序进行了测试:

private void button1_Click(object sender, EventArgs e)
{
    this.Icon = Properties.Resources.Gear;
}

private void button2_Click(object sender, EventArgs e)
{
    this.Icon = Properties.Resources.UAC_shield;
}

当程序运行时,单击每个按钮将更改表单图标(当然,也会更改任务栏中的图标)为指定的图标。我只是从Visual Studio附带的一组图标中选择了一些图标,并将它们添加到项目的资源文件中。
您应该能够添加一个简单的方法,在代码中的任何位置都可以调用该方法来设置图标(您也可以在Form_Load中调用它):
private void ChangeIconStatus(string statusText)
{
    Type type = this.GetType();
    System.Resources.ResourceManager resources =
    new System.Resources.ResourceManager(type.Namespace + ".Properties.Resources", this.GetType().Assembly);
    this.Icon = (System.Drawing.Icon)resources.GetObject(type.Namespace + ".Icons." + statusText + ".ico");
}

0

"this.Icon"解决一般图标问题...

但如果您想更改桌面应用程序的最小化图标,请按照以下步骤操作。如果您想覆盖所有可能性,这也可能起作用。

在WinForm应用程序中拖放一个控件“NotifyIcon”(工具箱 -> 常规控件)。它是透明的,所以将它放在某个角落不会影响任何事情。

单击窗体并重写RESIZE事件。

复制以下代码:

/// <summary>
/// GET - if the form is minimized, hide it from the task bar and show the system tray icon 
/// (represented by the NotifyIcon control)   
/// </summary>
private void Form1_Resize(object sender, EventArgs e)
{
        // CTRL - 
        if (this.WindowState == FormWindowState.Minimized)
        {
            // RESET - hide this from taskbar
            Hide();
            // SET - show system tray icon
            notifyIcon1.Visible = true;
                
            // INIT - tray icon
            // change this as you wish - from the Exe PATH, you have to have a
            // "Resources" directory with inside your icon. Just to not put 
            // every icon inside the exe directory...
            Icon tempIcon = Icon.ExtractAssociatedIcon("Resources/myIcon.ico");  
            
            notifyIcon1.Icon = tempIcon;
        }
        // RET
        return;
}

结果是,如果您的程序启动时是最小化的或将被最小化,图标将由代码设置。

此解决方案是在“主要”中必须放置的代码的补充。

        /// <summary>
        /// MAIN - with optional arguments
        /// </summary>
        public Form1(string[] arguments)
        {
            // INIT
            InitializeComponent();
            // INIT - icon of the desktop application
            Icon tempIcon = Icon.ExtractAssociatedIcon("Resources/myIcon.ico");
            this.Icon = tempIcon;
            // RET
            return;
        }

再见


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接