提取Windows中系统自带的图标资源
写应用程序,如果想使用Windows下的图标,可以使用Visual Studio中的图标,比如VS2008的 ImageLibrary(笔者已经打包上传到CSDN),也可以使用Windows系统自带的图标。
Windows系统自带了不少高质量的图标资源,只需要将其提取出来即可使用。
在Windows 95到Windows 10 1903之前的版本,都可以直接在dll中提取系统图标,比如最常用的图标都在shell32.dll中。
一、使用IconsExtract提取
可以使用 IconsExtract,它是 nirsoft开发的软件,该公司开发了许多工具软件,可以去官网查看, http://launcher.nirsoft.net/utilities_list.html有一个列表。
下图是Win10下使用IconsExtract
列出的shell32.dll中的图标:
如果想要提取(导出)图标,选中要导出的图标,可以多选,在右键弹出菜单中选择“Save Selected Icons”。
二、使用ResourceHacker提取
ResourceHacker也可以提取图标,它的功能强大之处在于可以替换资源和编译资源。对于提取图标,但它一次只能提取一个图标,如果要提取大量图标,很繁琐。同时它只能操作dll文件本身嵌入的资源,对Win10 1903及之后版本中的shell32.dll查看不了图标资源。
三、使用7zip解压缩DLL中的资源
其实,Windows下不管是EXE文件,还是DLL文件它都是一个ZIP压缩文件,都可以使用ZIP解压缩来查看内容。比如使用7zip来查看ResourceHacker.exe中的内容:
查看shell32.dll的内容:
其中的.rsrc
就是内嵌的资源文件所在目录。ICON图标文件就在其中:
但是在Win10 1903及之后版本,shell32.dll中并不包括图标资源了,它被分离到了C:\Windows\SystemResources\
下的同名mun文件中,即shell32.dll.mun
中
所以直接解压shell32.dll是无法提取图标文件的,需要使用7zip解压C:\Windows\SystemResources\shell32.dll.mun
下图是解压出来的文件:
四、号外
使用VC++创建Windows桌面程序读取并显示图标。
1#include <map>
2#include <vector>
3
4std::map<HICON,int> mapIcon;
5std::vector<HICON> vctIcon;
6HMODULE hShell32;
7
8void DebugError(DWORD errorCode)
9{
10 LPVOID lpMsgBuf;
11 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
12 NULL, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
13 (LPTSTR)&lpMsgBuf, 0, NULL);
14 OutputDebugString((LPTSTR)lpMsgBuf);
15 LocalFree(lpMsgBuf);
16}
17
18int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
19 _In_opt_ HINSTANCE hPrevInstance,
20 _In_ LPWSTR lpCmdLine,
21 _In_ int nCmdShow)
22{
23 UNREFERENCED_PARAMETER(hPrevInstance);
24 UNREFERENCED_PARAMETER(lpCmdLine);
25
26 // TODO: 在此处放置代码。
27 DWORD errorCode = 0;
28 HMODULE hShell32 = LoadLibrary(_T("shell32.dll"));
29 if (hShell32 == nullptr)
30 {
31 errorCode = GetLastError();
32 DebugError(errorCode);
33 return FALSE;
34 }
35 // 由于资源号达到80000+,所以取100000
36 for (int i = 1; i < 100000; ++i)
37 {
38 HICON hIcon = (HICON)LoadImage(hShell32, MAKEINTRESOURCE(i), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
39 if (hIcon != nullptr)
40 {
41 mapIcon[hIcon] = i;
42 vctIcon.push_back(hIcon);
43 }
44 }
45
46 // 初始化全局字符串
47 LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
48 LoadStringW(hInstance, IDC_WINDOWSPROJECT1, szWindowClass, MAX_LOADSTRING);
49 MyRegisterClass(hInstance);
50
51 // 执行应用程序初始化:
52 if (!InitInstance (hInstance, SW_SHOWMAXIMIZED))
53 {
54 FreeLibrary(hShell32);
55 return FALSE;
56 }
57
58 HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT1));
59
60 MSG msg;
61
62 // 主消息循环:
63 while (GetMessage(&msg, nullptr, 0, 0))
64 {
65 if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
66 {
67 TranslateMessage(&msg);
68 DispatchMessage(&msg);
69 }
70 }
71
72 return (int) msg.wParam;
73}
74
75void draw(HDC hdc)
76{
77 TCHAR buf[16];
78 int x = 0, y = 0;
79 DWORD maxY = 0;
80 ICONINFOEX info;
81 info.cbSize = sizeof(info);
82 for (int i = 0; i < vctIcon.size(); ++i)
83 {
84 if (GetIconInfoEx(vctIcon[i], &info))
85 {
86 if (!info.fIcon)
87 continue;
88
89 DrawIcon(hdc, x, y, vctIcon[i]);
90 int n = _stprintf_s(buf, ARRAYSIZE(buf), _T("%d"), mapIcon[vctIcon[i]]);
91 TextOut(hdc, x, y + info.yHotspot * 2 + 2, buf, n);
92 x += info.xHotspot * 3 + 2;
93 if (info.yHotspot > maxY)
94 maxY = info.yHotspot;
95 if (x >= 1900) {
96 y += maxY * 3 + 4;
97 x = 0;
98 }
99 }
100 }
101}
102
103LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
104{
105 switch (message)
106 {
107 case WM_COMMAND:
108 {
109 int wmId = LOWORD(wParam);
110 // 分析菜单选择:
111 switch (wmId)
112 {
113 case IDM_ABOUT:
114 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
115 break;
116 case IDM_EXIT:
117 DestroyWindow(hWnd);
118 break;
119 default:
120 return DefWindowProc(hWnd, message, wParam, lParam);
121 }
122 }
123 break;
124 case WM_PAINT:
125 {
126 PAINTSTRUCT ps;
127 HDC hdc = BeginPaint(hWnd, &ps);
128 // TODO: 在此处添加使用 hdc 的任何绘图代码...
129 draw(hdc);
130 EndPaint(hWnd, &ps);
131 }
132 break;
133 case WM_DESTROY:
134 for (int i = 0; i < vctIcon.size(); ++i)
135 {
136 DestroyIcon(vctIcon[i]);
137 }
138 FreeLibrary(hShell32);
139 PostQuitMessage(0);
140 break;
141 default:
142 return DefWindowProc(hWnd, message, wParam, lParam);
143 }
144 return 0;
145}
执行结果:
- 原文作者:Witton
- 原文链接:https://wittonbell.github.io/posts/2023/2023-05-05-提取Windows中系统自带的图标资源/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. 进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。