【发布时间】:2018-08-07 23:44:05
【问题描述】:
最近我做了一个程序,它加载一个可执行文件或 DLL 文件,枚举其中的所有图标资源,然后将每个图标资源作为 .ico 文件保存在一个文件夹中。但它使用直方图(如 this post 中所述)来避免保存重复的图标(看起来相同的图标)。
该程序首先从用户那里获取两条路径(用户必须在控制台窗口中键入它们)。其中一个是exe或dll文件的路径,另一个是要保存.ico文件的文件夹的路径。
然后程序通过调用LoadLibraryEx 加载exe 或dll 文件,并通过调用EnumResourceNames 枚举图标资源。
传递给EnumResourceNames 的回调函数将每个不重复的图标资源保存为具有唯一名称的 .ico 文件。保存文件的名称是这样的:1.ico、2.ico、3.ico、4.ico、.etc
我的完整代码和我的问题
问题是我的程序创建了损坏或未知的 .ico 文件,而不是真实的。
我的意思是,一些保存的图标有奇怪的图像,其中一些根本看不到!即使我使用WriteFile 函数将BITMAPFILEHEADER 结构写入每个.ico 文件。
只需编译并运行我的代码,然后在控制台窗口中输入以下内容:
C:\Windows\System32\shell32.dll
然后键入要保存 .ico 文件的现有文件夹的路径。
接下来,等待至少 4 到 7 秒,直到操作完成。
然后打开那个文件夹,看看图标!他们很可笑!
以下是我的代码。抱歉,如果 cmets 或变量和函数的名称中有一些拼写错误。无论如何,只有函数main() 和EnumIcons() 是重要的,并且一定要阅读代码下面的解释。
#include <iostream>
#include <conio.h>
#include <Windows.h>
#include <string>
#include <vector>
using namespace std;
string folderPath;
//Variables to store the number of
//successfully extracted icons.
UINT nSucceed = 0, nFail = 0;
typedef struct tagHISTOGRAM {
float bucket1; //Range 0-63
float bucket2; //Range 64-127
float bucket3; //Range 128-191
float bucket4; //Range 192-255
} HISTOGRAM, *PHISTOGRAM;
typedef struct tagIOV {
SIZE dimensions; //Width and height of the image
HISTOGRAM hgRed; //Histogram for red channel
HISTOGRAM hgGreen; //Histogram for green channel
HISTOGRAM hgBlue; //Histogram for blue channel
} IMAGE_OVERVIEW, *PIMAGE_OVERVIEW;
#define isInRange(n, s, e) (s <= n) && (n <= e)
//Constant used for the last parameter of CreateIconFromResource
#define ICO_VER 0x00030000
//Vector which stores IMAGE_OVERVIEW stuctures discribing all
//icons processed. When a new icon is being processed, the
//program checks all previous structures in the vector and
//then add the corresponding IMAGE_OVERVIEW structure to the
//vector.
vector<IMAGE_OVERVIEW> theIcons;
inline void incrementAppropriateBucket(PHISTOGRAM phg, BYTE pixel)
{
if (isInRange(pixel, 0, 63))
phg->bucket1++;
else if (isInRange(pixel, 64, 127))
phg->bucket2++;
else if (isInRange(pixel, 128, 191))
phg->bucket3++;
else if (isInRange(pixel, 192, 255))
phg->bucket4++;
}
//The following function divides each bucket total by the number
//of pixels in the entire image.
inline void finalizeHistogram(PHISTOGRAM phg, DWORD nPixels)
{
phg->bucket1 /= nPixels;
phg->bucket2 /= nPixels;
phg->bucket3 /= nPixels;
phg->bucket4 /= nPixels;
}
BOOL createImageOverview(HBITMAP hBmp, PIMAGE_OVERVIEW iov)
{
BITMAPINFO bmpInfo = {};
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
HDC DC = CreateCompatibleDC(NULL);
SelectObject(DC, hBmp);
if (!GetDIBits(DC, hBmp, 0, 0, NULL, &bmpInfo, DIB_RGB_COLORS))
{
ReleaseDC(NULL, DC);
DeleteDC(DC);
return FALSE;
}
bmpInfo.bmiHeader.biBitCount = 32;
bmpInfo.bmiHeader.biCompression = BI_RGB;
bmpInfo.bmiHeader.biHeight = abs(bmpInfo.bmiHeader.biHeight);
iov->dimensions.cx = bmpInfo.bmiHeader.biWidth;
iov->dimensions.cy = bmpInfo.bmiHeader.biHeight;
BYTE* pixels = new BYTE[bmpInfo.bmiHeader.biSizeImage];
if (!GetDIBits(DC, hBmp, 0, bmpInfo.bmiHeader.biHeight, (PVOID) pixels, &bmpInfo, DIB_RGB_COLORS))
{
delete[] pixels;
ReleaseDC(NULL, DC);
DeleteDC(DC);
return FALSE;
}
for (LONG Y = bmpInfo.bmiHeader.biHeight - 1;Y >= 0;Y--)
for (LONG X = 0;X < bmpInfo.bmiHeader.biWidth;X++)
{
BYTE R = pixels[(bmpInfo.bmiHeader.biWidth * Y + X) * 4 + 2];
incrementAppropriateBucket(&(iov->hgRed), R);
BYTE G = pixels[(bmpInfo.bmiHeader.biWidth * Y + X) * 4 + 1];
incrementAppropriateBucket(&(iov->hgGreen), G);
BYTE B = pixels[(bmpInfo.bmiHeader.biWidth * Y + X) * 4];
incrementAppropriateBucket(&(iov->hgBlue), B);
}
DWORD nPixels = bmpInfo.bmiHeader.biWidth * bmpInfo.bmiHeader.biHeight;
finalizeHistogram(&(iov->hgRed), nPixels);
finalizeHistogram(&(iov->hgGreen), nPixels);
finalizeHistogram(&(iov->hgBlue), nPixels);
delete[] pixels;
ReleaseDC(NULL, DC);
DeleteDC(DC);
return TRUE;
}
float sumUpBucketDifferances(const HISTOGRAM hg1, const HISTOGRAM hg2)
{
float result = 0;
result += abs(hg1.bucket1 - hg2.bucket1);
result += abs(hg1.bucket2 - hg2.bucket2);
result += abs(hg1.bucket3 - hg2.bucket3);
result += abs(hg1.bucket4 - hg2.bucket4);
return result;
}
float compareImages(const IMAGE_OVERVIEW iov1, const IMAGE_OVERVIEW iov2)
{
float result = 0;
result += sumUpBucketDifferances(iov1.hgRed, iov2.hgRed);
result += sumUpBucketDifferances(iov1.hgGreen, iov2.hgGreen);
result += sumUpBucketDifferances(iov1.hgBlue, iov2.hgBlue);
return result;
}
BOOL isDuplicate(const IMAGE_OVERVIEW iov)
{
size_t s = theIcons.size();
for (size_t i = 0;i < s;i++)
{
if ((theIcons[i].dimensions.cx != iov.dimensions.cx) ||
(theIcons[i].dimensions.cy != iov.dimensions.cy))
continue;
if (compareImages(theIcons[i], iov) < 0.1)
return TRUE;
}
return FALSE;
}
BOOL CALLBACK EnumIcons(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)
{
HRSRC hRes = FindResource(hModule, lpszName, lpszType);
if (!hRes)
{
nFail++;
return TRUE;
}
DWORD icoSize = SizeofResource(hModule, hRes);
if (!icoSize)
{
nFail++;
return TRUE;
}
HGLOBAL hIcoData = LoadResource(hModule, hRes);
if (!hIcoData)
{
nFail++;
return TRUE;
}
BYTE* icoData = (BYTE *) LockResource(hIcoData);
if (!icoData)
{
FreeResource(hIcoData);
nFail++;
return TRUE;
}
//Checking whether the icon is dupplicate
HICON hIcon = CreateIconFromResource(icoData, icoSize, TRUE, ICO_VER);
if (!hIcon)
{
FreeResource(hIcoData);
nFail++;
return TRUE;
}
ICONINFO ii;
if (!GetIconInfo(hIcon, &ii))
{
DestroyIcon(hIcon);
FreeResource(hIcoData);
nFail++;
return TRUE;
}
IMAGE_OVERVIEW iov;
ZeroMemory(&iov, sizeof(IMAGE_OVERVIEW));
BOOL r = createImageOverview(ii.hbmColor, &iov);
DeleteObject(ii.hbmColor);
DeleteObject(ii.hbmMask);
DestroyIcon(hIcon);
if (!r)
{
FreeResource(hIcoData);
nFail++;
return TRUE;
}
if (isDuplicate(iov))
{
FreeResource(hIcoData);
nFail++;
return TRUE;
}
theIcons.push_back(iov);
//End of checking whether the icon is dupplicate
//Note that the first icon is saved as 1.ico,
//the second is saved as 2.ico, and so on. So
//the number of the current icon is equal to
//the number of the previously saved icons + 1
int icoNumber = nSucceed + 1;
PSTR strIcoNumber = (PSTR) VirtualAlloc((LPVOID) NULL, 10, MEM_COMMIT, PAGE_READWRITE);
itoa(icoNumber, strIcoNumber, 10);
string icoPath(folderPath);
icoPath.append(strIcoNumber);
icoPath.append(".ico");
VirtualFree(strIcoNumber, 0, MEM_RELEASE);
PCSTR strIcoPath = icoPath.c_str();
HANDLE ico = CreateFile(strIcoPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (ico == INVALID_HANDLE_VALUE)
{
FreeResource(hIcoData);
nFail++;
return TRUE;
}
DWORD bytesWritten;
BITMAPFILEHEADER bfh;
bfh.bfType = 0x4d42;
bfh.bfSize = icoSize + sizeof(BITMAPFILEHEADER);
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bfh.bfReserved1 = bfh.bfReserved2 = 0;
r = WriteFile(ico, &bfh, sizeof(BITMAPFILEHEADER), &bytesWritten, NULL);
if (!r)
{
FreeResource(hIcoData);
CloseHandle(ico);
nFail++;
return TRUE;
}
r = WriteFile(ico, icoData, icoSize, &bytesWritten, NULL);
FreeResource(hIcoData);
CloseHandle(ico);
if (!r)
{
nFail++;
return TRUE;
}
nSucceed++;
return TRUE;
}
void main()
{
cout << "Enter the path where your EXE or DLL is located:" << endl;
string modulePath;
getline(cin, modulePath);
cout << "Now, enter the path of the folder where the .ico files are to be saved:" << endl;
getline(cin, folderPath);
//If the folder path doesn't have a trailing backslash, add one!
if (folderPath.rfind('\\') != folderPath.length() - 1)
folderPath.push_back('\\');
cout << "Extracting icons..." << endl;
PCSTR strModulePath = modulePath.c_str();
HMODULE hModule = LoadLibraryEx(strModulePath, NULL, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
if (!hModule)
{
cout << "Unable to load the DLL or EXE." << endl;
getch();
return;
}
BOOL result = EnumResourceNames(hModule, MAKEINTRESOURCE(RT_ICON), (ENUMRESNAMEPROC) EnumIcons, NULL);
FreeLibrary(hModule);
if (!result)
{
cout << "Unable to extract icons." << endl;
getch();
return;
}
cout << nSucceed << " icons were successfully extracted." << endl;
cout << "Failed to extract " << nFail << " icons." << endl;
getch();
}
嗯,我们有四个全局变量。其中之一是folderPath。正如我之前提到的,我们从用户那里获取文件夹的路径。此操作在main() 函数中执行,路径存储在folderPath 变量中。我将此变量定义为全局变量,因为它旨在供 EnumIcons() 函数和 main() 函数访问。
现在,看看main() 函数。这很容易理解。
所以在main()函数中,在接受用户输入后,我们调用LoadLibraryEx,然后调用EnumResourceNames,传递一个指向EnumIcons回调函数的指针。 EnumIcons 函数会为每个成功保存的图标增加 nSucceed 全局变量,并为每个未能保存的图标或重复图标增加 nFail。
现在,看看EnumIcons 函数,它保存在 EXE 或 DLL 文件中找到的每个非重复图标。这个函数里面的代码很清楚,除了它检查图标是否重复的一部分。
这部分代码以以下注释开头:
//Checking whether the icon is dupplicate
并以以下注释结束:
//End of checking whether the icon is dupplicate
我只是建议您跳过该部分功能,因为它与我的主要问题无关。在EnumIcons 函数中,我调用了FindResource、LoadResource、LockResource、SizeofResource、CreateFile 和WriteFile 等函数。
只需检查我是否调用了这些函数并进行了正确的错误检查。不要注意检测重复图标的部分。
解决方案:
今天,我使用@Barmak Shemirani 的回答中的信息对我的代码进行了一些更改并解决了问题。我只是想知道#pragma 指令是什么(在定义ICONDIR 和ICONDIRENTRY 结构之前和之后使用的指令)。这是我修改后的代码:
编辑:代码已更新,并进行了细微改进。
#include <iostream>
#include <conio.h>
#include <Windows.h>
#include <string>
#include <vector>
using namespace std;
//Variables to store the number of
//successfully extracted icons and
//the icons that are dupplicate or
//failed to extract.
UINT nSucceed = 0, nFail = 0;
typedef struct tagHISTOGRAM {
float bucket1; //Range 0-63
float bucket2; //Range 64-127
float bucket3; //Range 128-191
float bucket4; //Range 192-255
} HISTOGRAM, *PHISTOGRAM;
typedef struct tagIOV {
SIZE dimensions; //Width and height of the image
HISTOGRAM hgRed; //Histogram for red channel
HISTOGRAM hgGreen; //Histogram for green channel
HISTOGRAM hgBlue; //Histogram for blue channel
} IMAGE_OVERVIEW, *PIMAGE_OVERVIEW;
#define isInRange(n, s, e) (s <= n) && (n <= e)
//Constant used for the last parameter of CreateIconFromResource
#define ICO_VER 0x00030000
//Vector which stores IMAGE_OVERVIEW stuctures discribing all
//icons processed. When a new icon is being processed, the
//program checks all previous structures in the vector and
//then add the corresponding IMAGE_OVERVIEW structure to the
//vector.
vector<IMAGE_OVERVIEW> theIcons;
#pragma pack(push, 2)
typedef struct
{
BYTE bWidth;
BYTE bHeight;
BYTE bColorCount;
BYTE bReserved;
WORD wPlanes;
WORD wBitCount;
DWORD dwBytesInRes;
DWORD dwImageOffset;
} ICONDIRENTRY, *LPICONDIRENTRY;
typedef struct
{
WORD idReserved;
WORD idType;
WORD idCount;
ICONDIRENTRY idEntries[1];
} ICONDIR, *LPICONDIR;
#pragma pack(pop)
inline void incrementAppropriateBucket(PHISTOGRAM phg, BYTE pixel)
{
if (isInRange(pixel, 0, 63))
phg->bucket1++;
else if (isInRange(pixel, 64, 127))
phg->bucket2++;
else if (isInRange(pixel, 128, 191))
phg->bucket3++;
else if (isInRange(pixel, 192, 255))
phg->bucket4++;
}
//The following function divides each bucket total by the number
//of pixels in the entire image.
inline void finalizeHistogram(PHISTOGRAM phg, DWORD nPixels)
{
phg->bucket1 /= nPixels;
phg->bucket2 /= nPixels;
phg->bucket3 /= nPixels;
phg->bucket4 /= nPixels;
}
BOOL createImageOverview(HBITMAP hBmp, PIMAGE_OVERVIEW iov)
{
BITMAPINFO bmpInfo = {};
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
HDC DC = CreateCompatibleDC(NULL);
SelectObject(DC, hBmp);
if (!GetDIBits(DC, hBmp, 0, 0, NULL, &bmpInfo, DIB_RGB_COLORS))
{
DeleteDC(DC);
return FALSE;
}
bmpInfo.bmiHeader.biBitCount = 32;
bmpInfo.bmiHeader.biCompression = BI_RGB;
bmpInfo.bmiHeader.biHeight = abs(bmpInfo.bmiHeader.biHeight);
iov->dimensions.cx = bmpInfo.bmiHeader.biWidth;
iov->dimensions.cy = bmpInfo.bmiHeader.biHeight;
BYTE* pixels = new BYTE[bmpInfo.bmiHeader.biSizeImage];
if (!GetDIBits(DC, hBmp, 0, bmpInfo.bmiHeader.biHeight, (PVOID) pixels, &bmpInfo, DIB_RGB_COLORS))
{
delete[] pixels;
DeleteDC(DC);
return FALSE;
}
for (LONG Y = bmpInfo.bmiHeader.biHeight - 1;Y >= 0;Y--)
for (LONG X = 0;X < bmpInfo.bmiHeader.biWidth;X++)
{
BYTE R = pixels[(bmpInfo.bmiHeader.biWidth * Y + X) * 4 + 2];
incrementAppropriateBucket(&(iov->hgRed), R);
BYTE G = pixels[(bmpInfo.bmiHeader.biWidth * Y + X) * 4 + 1];
incrementAppropriateBucket(&(iov->hgGreen), G);
BYTE B = pixels[(bmpInfo.bmiHeader.biWidth * Y + X) * 4];
incrementAppropriateBucket(&(iov->hgBlue), B);
}
DWORD nPixels = bmpInfo.bmiHeader.biWidth * bmpInfo.bmiHeader.biHeight;
finalizeHistogram(&(iov->hgRed), nPixels);
finalizeHistogram(&(iov->hgGreen), nPixels);
finalizeHistogram(&(iov->hgBlue), nPixels);
delete[] pixels;
DeleteDC(DC);
return TRUE;
}
float sumUpBucketDifferances(const HISTOGRAM hg1, const HISTOGRAM hg2)
{
float result = 0;
result += abs(hg1.bucket1 - hg2.bucket1);
result += abs(hg1.bucket2 - hg2.bucket2);
result += abs(hg1.bucket3 - hg2.bucket3);
result += abs(hg1.bucket4 - hg2.bucket4);
return result;
}
float compareImages(const IMAGE_OVERVIEW iov1, const IMAGE_OVERVIEW iov2)
{
float result = 0;
result += sumUpBucketDifferances(iov1.hgRed, iov2.hgRed);
result += sumUpBucketDifferances(iov1.hgGreen, iov2.hgGreen);
result += sumUpBucketDifferances(iov1.hgBlue, iov2.hgBlue);
return result;
}
BOOL isDuplicate(const IMAGE_OVERVIEW iov)
{
size_t s = theIcons.size();
for (size_t i = 0;i < s;i++)
{
if ((theIcons[i].dimensions.cx != iov.dimensions.cx) ||
(theIcons[i].dimensions.cy != iov.dimensions.cy))
continue;
if (compareImages(theIcons[i], iov) < 0.1)
return TRUE;
}
return FALSE;
}
BOOL CALLBACK EnumIcons(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)
{
if (!lParam)
return FALSE;
string folderPath = (char *) lParam;
HRSRC hRes = FindResource(hModule, lpszName, lpszType);
if (!hRes)
{
nFail++;
return TRUE;
}
DWORD icoSize = SizeofResource(hModule, hRes);
if (!icoSize)
{
nFail++;
return TRUE;
}
HGLOBAL hIcoData = LoadResource(hModule, hRes);
if (!hIcoData)
{
nFail++;
return TRUE;
}
BYTE* icoData = (BYTE *) LockResource(hIcoData);
if (!icoData)
{
FreeResource(hIcoData);
nFail++;
return TRUE;
}
HICON hIcon = CreateIconFromResource(icoData, icoSize, TRUE, ICO_VER);
if (!hIcon)
{
FreeResource(hIcoData);
nFail++;
return TRUE;
}
ICONINFOEX ii = {sizeof(ICONINFOEX)};
if (!GetIconInfoEx(hIcon, &ii))
{
DestroyIcon(hIcon);
FreeResource(hIcoData);
nFail++;
return TRUE;
}
BITMAP bmp;
if (!GetObject(ii.hbmColor, sizeof(BITMAP), &bmp))
{
DeleteObject(ii.hbmColor);
DeleteObject(ii.hbmMask);
DestroyIcon(hIcon);
FreeResource(hIcoData);
nFail++;
return TRUE;
}
ICONDIR icoDir = {0};
icoDir.idType = 1;
icoDir.idCount = 1;
icoDir.idEntries[0].bWidth = (BYTE) bmp.bmWidth;
icoDir.idEntries[0].bHeight = (BYTE) bmp.bmHeight;
icoDir.idEntries[0].wPlanes = bmp.bmPlanes;
icoDir.idEntries[0].wBitCount = bmp.bmBitsPixel;
icoDir.idEntries[0].dwBytesInRes = icoSize;
icoDir.idEntries[0].dwImageOffset = sizeof(ICONDIR);
//Checking whether the icon is duplicate
IMAGE_OVERVIEW iov;
ZeroMemory(&iov, sizeof(IMAGE_OVERVIEW));
BOOL r = createImageOverview(ii.hbmColor, &iov);
DeleteObject(ii.hbmColor);
DeleteObject(ii.hbmMask);
DestroyIcon(hIcon);
if (!r)
{
FreeResource(hIcoData);
nFail++;
return TRUE;
}
if (isDuplicate(iov))
{
FreeResource(hIcoData);
nFail++;
return TRUE;
}
theIcons.push_back(iov);
//End of checking whether the icon is dupplicate
//Note that the first icon is saved as 1.ico,
//the second is saved as 2.ico, and so on. So
//the number of the current icon is equal to
//the number of the previously saved icons + 1
int icoNumber = nSucceed + 1;
char* strIcoNumber = (char *) malloc(10);
itoa(icoNumber, strIcoNumber, 10);
string icoPath(folderPath);
icoPath.append(strIcoNumber);
icoPath.append(".ico");
HANDLE ico = CreateFile(icoPath.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (ico == INVALID_HANDLE_VALUE)
{
FreeResource(hIcoData);
nFail++;
return TRUE;
}
DWORD bytesWritten;
r = WriteFile(ico, &icoDir, sizeof(ICONDIR), &bytesWritten, NULL);
if (!r)
{
FreeResource(hIcoData);
CloseHandle(ico);
nFail++;
return TRUE;
}
r = WriteFile(ico, icoData, icoSize, &bytesWritten, NULL);
FreeResource(hIcoData);
CloseHandle(ico);
if (!r)
{
nFail++;
return TRUE;
}
nSucceed++;
return TRUE;
}
void main()
{
cout << "Enter the path where your EXE or DLL is located:" << endl;
string modulePath;
getline(cin, modulePath);
cout << "Now, enter the path of the folder where the .ico files are to be saved:" << endl;
string folderPath;
getline(cin, folderPath);
//If the folder path doesn't have a trailing backslash, add one!
if (folderPath.rfind('\\') != folderPath.length() - 1)
folderPath.push_back('\\');
cout << "Extracting icons..." << endl;
HMODULE hModule = LoadLibraryEx(modulePath.c_str(), NULL, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
if (!hModule)
{
cout << "Unable to load the DLL or EXE." << endl;
getch();
return;
}
BOOL result = EnumResourceNames(hModule, MAKEINTRESOURCE(RT_ICON), (ENUMRESNAMEPROC) EnumIcons, (LONG_PTR) (folderPath.c_str()));
FreeLibrary(hModule);
if (!result)
{
cout << "Unable to extract icons." << endl;
getch();
return;
}
cout << nSucceed << " icons were successfully extracted." << endl;
cout << nFail << " icons were dupplicates or could not be extracted." << endl;
getch();
}
【问题讨论】:
-
如果您需要解决此问题的帮助,我建议您创建一个minimal reproducible example。您发布的内容中有很多不必要的信息和代码。直方图的内容似乎与您的实际问题完全无关。
-
#pragma pack更改结构对齐方式。例如,在struct my_struct { WORD w; int i; };中,w有 2 个字节,i有 4 个字节。但总的sizeof结构是8,因为编译器为w添加了2 个额外的字节填充。#pragma pack(push, 2)或#pragma pack(push, 1)告诉编译器不要添加填充。#pragam pack(pop)恢复默认对齐方式。顺便说一句,您仍在使用VirtualAlloc。请勿致电ReleaseDC,除非在GetDC或GetWindowDC之后进行清理。在CreateDC...之后使用DeleteDC进行清理 -
@BarmakShemirani 感谢您对
#pragma pack的解释。好吧,我编辑了我的问题并删除了ReleaseDC函数调用,这次我使用了malloc。如果你在我的代码的任何部分看到VirtualAlloc,请告诉我你看到的函数和行号。然后我会解决这个问题。我还将folderPath定义为main()内部的局部变量,然后将(LONG_PTR) (folderPath.c_str())作为调用EnumResources的最后一个参数传递...
标签: c++ winapi resources icons