admin 管理员组

文章数量: 887021

写应用程序,如果想使用Windows下的图标,可以使用Visual Studio中的图标,比如VS2008的ImageLibrary(笔者已经打包上传到CSDN),也可以使用Windows系统自带的图标。

Windows系统自带了不少高质量的图标资源,只需要将其提取出来即可使用。

在Windows 95到Windows 10 1903之前的版本,都可以直接在dll中提取系统图标,比如最常用的图标都在shell32.dll中。

一、使用IconsExtract提取

可以使用IconsExtract,它是nirsoft开发的软件,该公司开发了许多工具软件,可以去官网查看,http://launcher.nirsoft/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桌面程序读取并显示图标。

#include <map>
#include <vector>

std::map<HICON,int> mapIcon;
std::vector<HICON> vctIcon;
HMODULE hShell32;

void DebugError(DWORD errorCode)
{
    LPVOID lpMsgBuf;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                NULL, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                (LPTSTR)&lpMsgBuf, 0, NULL);
    OutputDebugString((LPTSTR)lpMsgBuf);
    LocalFree(lpMsgBuf);
}

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: 在此处放置代码。
    DWORD errorCode = 0;
    HMODULE hShell32 = LoadLibrary(_T("shell32.dll"));
    if (hShell32 == nullptr)
    {
        errorCode = GetLastError();
        DebugError(errorCode);
        return FALSE;
    }
    // 由于资源号达到80000+,所以取100000
    for (int i = 1; i < 100000; ++i)
    {
        HICON hIcon = (HICON)LoadImage(hShell32, MAKEINTRESOURCE(i), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
        if (hIcon != nullptr)
        {
          mapIcon[hIcon] = i;
          vctIcon.push_back(hIcon);
        }
    }

    // 初始化全局字符串
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_WINDOWSPROJECT1, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // 执行应用程序初始化:
    if (!InitInstance (hInstance, SW_SHOWMAXIMIZED))
    {
        FreeLibrary(hShell32);
        return FALSE;
    }

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT1));

    MSG msg;

    // 主消息循环:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}

void draw(HDC hdc)
{
   TCHAR buf[16];
   int x = 0, y = 0;
   DWORD maxY = 0;
   ICONINFOEX info;
   info.cbSize = sizeof(info);
   for (int i = 0; i < vctIcon.size(); ++i)
   {
      if (GetIconInfoEx(vctIcon[i], &info))
      {
            if (!info.fIcon)
              continue;

            DrawIcon(hdc, x, y, vctIcon[i]);
            int n = _stprintf_s(buf, ARRAYSIZE(buf), _T("%d"), mapIcon[vctIcon[i]]);
            TextOut(hdc, x, y + info.yHotspot * 2 + 2, buf, n);
            x += info.xHotspot * 3 + 2;
            if (info.yHotspot > maxY)
              maxY = info.yHotspot;
            if (x >= 1900) {
              y += maxY * 3 + 4;
              x = 0;
            }
      }
   }
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // 分析菜单选择:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: 在此处添加使用 hdc 的任何绘图代码...
            draw(hdc);            
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        for (int i = 0; i < vctIcon.size(); ++i)
        {
            DestroyIcon(vctIcon[i]);
        }
        FreeLibrary(hShell32);
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

执行结果:

本文标签: 图标 系统自带 资源 Windows