首先Win32的话还是MSDN开路:
1.正规Win32开发方式
正规做法网上一搜一大把,用的IDE主要是VS,使用资源文件->添加->资源,导入*.ico文件,由VS自动分配IDI ID序号的方法。例如:
visual studio 2019如何给应用程序增加图标_visual studio 2019windows桌面应用怎么添加图标-优快云博客
这种情况下ico文件应该会被编译至exe可执行文件内,获得图标文件的方法,得到HICON作为资源句柄,在后面需要使用图标的时候将该句柄传入。
HICON hMyIco = LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(IDI_SOMEICOID));
那如果是野路子VS Code或者只有MingW编译器,没有完整的资源管理系统的呢……
2.windres编译ico文件
优快云 上几乎关于windres的资料都被设置为了VIP可见,万恶的资本主义T_T
windres是MingW(可能其他win平台的编译器也会?)附带的一个工具,在MingW可以正常调用的情况下应该是可以使用命令行调用windres工具。在此处的作用大概是将各类资源文件编译为.o文件,在链接时和主程序组装在一起。
2.1生成步骤
以编译ico文件举例,我们已经准备好了目标图标文件"my_icon.ico",并需要一个头文件"resource.h",该头文件用于标识符号IDI_MYICON的数字ID,应用程序会用ID最小的作为资源管理器显示的默认图标 (*来源请求)。内容如下:
#ifndef _RESOURCE_H
#define _RESOURCE_H
#define IDI_MYICON 1 //应用程序会用ID最小的作为资源管理器显示的默认图标 (*来源请求)
#endif
需要一个资源文件".rc",用于将符号IDI_MYICON和.ico文件路径绑定在一起。(当然.rc文件还可以用来定义窗口菜单栏等布局,在万能的记事本前即使没有可视化编辑器也什么都能改):
#include "resource.h"
IDI_MYICON ICON "my_icon.ico"
使用命令行启动windres工具将.rc文件定义的资源信息、窗口布局信息等等编译为目标文件"ico_out.o"。参数 -i 输入文件路径,-o输出文件路径:
windres -i ico.rc -o ico_out.o
最后在编译器上加入链接ico_out.o命令:
g++.exe "${fileDirname}\ico_out.o" -g "${fileDirname}\Test.cpp" -o "D:\${fileDirname}\Test.exe"
注意之前头文件定义的值足够小(不知道多少算足够小,目测30以内),程序默认图标会从控制台图标变为之前指定的"my_icon.ico"
(你看这个人是不是想摸鱼?)
3.LoadImage() 从文件加载(未验证)
大概的用法例如:
LoadImageA(
NULL, // 程序句柄
".\\my_icon.ico", //文件名称
IMAGE_ICON, //类型为图表
0, //实际资源宽度
0, //实际资源高度。
LR_LOADFROMFILE); //从 名称 (图标、光标或位图文件指定的文件) 加载独立图像。
此方法需要额外的文件访问,可能所以不被MSDN推荐?
如果 hInst 参数为 NULL 且 fuLoad 参数包含LR_LOADFROMFILE值,则 name 是包含独立资源 (图标、光标或位图文件) 的文件的名称,例如 。
c:\myicon.ico
用法未知,虽然是可以加载.ico文件但,lz懒得测试了,LoadImage()返回句柄HANDLE,不知道是否需要强制转换为HICON虽然可能都是void*类型。
4.加载都加载啦用一下吧?
最近常用显示图标的两个地方:
4.1窗口图标
如果主程序入口是
_tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
的话程序则按Win32GUI程序启动,即默认不弹出控制台。此时需要注册窗体重新制定窗口图标:
HICON hMyIcon LoadIcon(hInstance, MAKEINTRESOURCE(IDI_FISHICON))
WNDCLASS wndclass;
// ... 其他配置项目
wndclass.hIcon = hMyIcon; //将HICON传入
RegisterClass(&wndclass) // 注册窗体
4.2托盘图标
依然是把HICON句柄传给目标加载就好了
NOTIFYICONDATA nid;
nid.cbSize = (DWORD)sizeof(NOTIFYICONDATA);
nid.hWnd = hWnd;
nid.uID = 0; // IDR_MAINFRAME;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
nid.uCallbackMessage = WM_TO_TRAY;//自定义的消息 处理托盘图标事件
nid.hIcon = hMyIcon;
lstrcpy(nid.szTip, _T("文字……"));//鼠标放在托盘图标上时显示的文字
Shell_NotifyIcon(NIM_ADD, &nid);//在托盘区添加图标
4.3根据资源管理器图标大小显示不同尺寸的图标
7z解一个可执行文件时,目录结构如下:
.rsrc
├─GROUP_ICON
│ IDI_MAIN_ICON
│
├─ICON
│ 10
│ 11.ico
│ 12.ico
│ ...等一系列不同大小的ico
IDI_MAIN_ICON用sib-icon-studio打开发现是打包了12种尺寸图标的包,看这个名字很像是可用的图标。但尚不清楚如何制作。
未验证,只负责指路……LZ只是说不同分辨率图标“嵌入(embed)”,而没有提到具体操作方式。
windows - How to package several icons for different sizes in a VS C++ app? - Stack Overflow
一些题外话
exe解包可以用7z,但有些格式还是不支持(找不到ico文件)
编辑ico的话PS要装"ICOFormat.8BI"插件,但部分格式可能仍然不支持。
ico编辑器可以用sib-icon-studio,绿色版万岁!