博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ICON文件保存
阅读量:6311 次
发布时间:2019-06-22

本文共 14186 字,大约阅读时间需要 47 分钟。

这两天想做一下windows系统下图标的修改,让程序有更新的时候能够更新图标的外观,达到提醒的作用,360,QQ经常采用这种方式进行更新的提示,也有采用弹框的方式来提示,用新版QVOD的同事可能见到过类似的。废话不说,我的思路是:

(1)检测程序更新

(2)检测windows桌面图标中是够含有需要的,如果没有则需要创建,如果有则准备更新图标

(3)根据跟新的内容,程序自己创建新的图像,修改快捷方式的图标

 

这种方法需要开机之后,存在一个系统进程来检测这种更新,360就是这样干的~~还有一个弊端是程序需要检测桌面快捷方式的信息来判断是不是自己想去修改的,OK ,这个问题其实可以通过LNK文件的属性,应用信息,名字等问题来解决。 下面是实现过程

1 ICON文件的操作

ICON文件的格式和BMP文件的格式的类似,不过增加了层数的东西,一个ICON文件中可能有几份数据,不同的分辨率,ICON文件的格式主要定义如下:

//ICON文件存储格式typedef struct{    byte        bwidth;          // width, in pixels, of the image    byte        bheight;         // height, in pixels, of the image    byte        bcolorcount;     // number of colors in image (0 if >=8bpp)    byte        breserved;       // reserved ( must be 0)    WORD        wplanes;         // color planes    WORD        wbitcount;       // bits per pixel    DWORD       dwbytesinres;    // how many bytes in this resource?    DWORD       dwimageoffset;   // where in the file is this image?} ICONDIRENTRY, *LPICONDIRENTRY;//ICON文件目录typedef struct {    WORD            idReserved;   // Reserved    WORD            idType;       // resource type (1 for icons)    WORD            idCount;      // how many images?    ICONDIRENTRY    idEntries[1]; // the entries for each image} ICONDIR, *LPICONDIR;//ICON文件数据存储格式typedef struct{    BITMAPINFOHEADER    icheader;      // dib header    RGBQUAD                iccolors[1];   // color table    byte                icxor[1];      // dib bits for xor mask    byte                icand[1];      // dib bits for and mask} iconimage, *lpiconimage;
 
 
 
 
 
 
 
 
 
 
 
 
//图像数据存储struct stImageData{    BITMAPINFOHEADER   icheader;              // ptr to header    byte*          icxor ;    byte*          icand ;    stImageData()    {        icand = NULL ;        icxor = NULL ;    }};//ICON图像整体组成struct  stIconData{    int num ;    stImageData data[1];    stIconData()    {        num = 0 ;     }};struct stIcon{    ICONDIR *dir ;    stIconData *icon ;    stIcon()    {        dir = NULL ;        icon = NULL ;    }};
 
 
bool CIconOperate::ReadIcon(const string _str){    fstream fin ;    fin.open(_str.c_str(),ios_base::binary | ios_base::in);    if (!fin.is_open())    {        return false ;    }    ICONDIR dirTemp ;    //reserved    fin.read((char*)(&dirTemp.idReserved),sizeof(WORD));    //type    fin.read((char*)(&dirTemp.idType),sizeof(WORD));    //num    fin.read((char*)(&dirTemp.idCount),sizeof(WORD));    //image data header    byte *pBuffer = new byte[3 * sizeof(WORD) + dirTemp.idCount * sizeof(ICONDIRENTRY)] ; // 变长数据操作    m_IconDir = (ICONDIR *)(pBuffer);    m_IconDir->idCount = dirTemp.idCount ;    m_IconDir->idReserved = dirTemp.idReserved ;    m_IconDir->idType = dirTemp.idType ;    for (int i = 0 ; i < dirTemp.idCount ; ++i)    {        fin.read((char*)(&m_IconDir->idEntries[i]),sizeof(ICONDIRENTRY));    }    //img data     byte *pBufferData = new byte[sizeof(int) + dirTemp.idCount * sizeof(stImageData)];    m_IconData = (stIconData*)pBufferData ;    m_IconData->num = m_IconDir->idCount ;    for (int i = 0 ; i < m_IconDir->idCount ; ++ i)    {        //SEEK        fin.seekg(m_IconDir->idEntries[i].dwimageoffset,ios_base::beg) ;        //READ BITMAPINFOHEADER        fin.read((char*)(&m_IconData->data[i].icheader),sizeof(BITMAPINFOHEADER));        //READ XOR DATA        int xornum = WIDTHBYTES(m_IconDir->idEntries[i].bwidth,m_IconDir->idEntries[i].wbitcount)                        * m_IconDir->idEntries[i].bheight;         int andnum = WIDTHBYTES(m_IconDir->idEntries[i].bwidth,1)            * m_IconDir->idEntries[i].bheight;        m_IconData->data[i].icxor = new byte[xornum];        fin.read((char*)(m_IconData->data[i].icxor),xornum);        //READ AND DATA        m_IconData->data[i].icand = new byte[andnum];        fin.read((char*)(m_IconData->data[i].icand),andnum);    }    fin.close();    return true ;}

写数据

bool CIconOperate::SaveIcon(const string _str){    if (m_IconDir == NULL || m_IconData == NULL)        return false ;    //int  width  = 64 ;    //int  heigth = 64 ;    //int  ppx = 32 ;    fstream fout;    fout.open(_str.c_str(),ios_base::out | ios_base::binary);      //reserved     WORD wData = 0 ;    fout.write((char*)(&wData),sizeof(WORD));    //type    wData = 1 ;    fout.write((char*)(&wData),sizeof(WORD));    //num    wData = m_IconDir->idCount ;    fout.write((char*)(&wData),sizeof(WORD));    //write ICONDIRENTRY数据    for (int i = 0 ; i < m_IconDir->idCount ; ++i)    {        //ICONDIRENTRY结构        ICONDIRENTRY iconData ;        iconData.bwidth  = m_IconDir->idEntries[i].bwidth ;        iconData.bheight = m_IconDir->idEntries[i].bheight ;        iconData.bcolorcount  =  0;        iconData.breserved    =  0 ;        iconData.wplanes      =  1 ;        iconData.wbitcount    =  m_IconDir->idEntries[i].wbitcount ;        iconData.dwbytesinres = sizeof(BITMAPINFOHEADER)             +  iconData.bheight * WIDTHBYTES(iconData.bwidth,iconData.wbitcount)             +  iconData.bheight * WIDTHBYTES(iconData.bwidth,1);        iconData.dwimageoffset =  CalculateImageOffset(i) ;         fout.write((char*)(&iconData),sizeof(ICONDIRENTRY));    }    for (int i = 0 ; i < m_IconDir->idCount ; ++i)    {        //BITMAPINFOHEADER结构        BITMAPINFOHEADER tBitHeader;        tBitHeader.biSize          = sizeof(BITMAPINFOHEADER);        tBitHeader.biWidth         = m_IconDir->idEntries[i].bwidth ;        tBitHeader.biHeight        = m_IconDir->idEntries[i].bheight*2 ;        tBitHeader.biPlanes        = 1 ;        tBitHeader.biBitCount      = m_IconDir->idEntries[i].wbitcount ;        tBitHeader.biCompression   = 0 ;        tBitHeader.biSizeImage     = 0;        tBitHeader.biXPelsPerMeter = 0 ;        tBitHeader.biYPelsPerMeter = 0 ;        tBitHeader.biClrUsed       = 0 ;        tBitHeader.biClrImportant  = 0 ;        fout.write((char*)(&tBitHeader),sizeof(BITMAPINFOHEADER));        fout.write((char*)m_IconData->data[i].icxor,tBitHeader.biHeight/2 * WIDTHBYTES(tBitHeader.biWidth,tBitHeader.biBitCount));        fout.write((char*)m_IconData->data[i].icand,tBitHeader.biHeight/2 * WIDTHBYTES(tBitHeader.biWidth,1));    }    fout.close();        return true ;}
 
 
 
 
 
vector
* CFileSearch::SearchLinkByName(const CString& _str) { m_FindList.clear(); m_strFind = _str ; GetPath(m_strDeskTopPath,m_strQuickLanchPath); if(GetDesktopIShellFolder()) { GetIEunmIDList(m_pIShellFolder,FALSE,m_mode); } fprintf(fp,"\n\n\n\n"); for (int i = 0 ; i < m_FindList.size() ; i++) { fprintf(fp,"%s\n",m_FindList[i].c_str()); } return &m_FindList ;}//获取桌面文件夹和快速启动文件夹的路径 int CFileSearch::GetPath(char *DeskTop, char* AppData) { CRegKey m_reg; if(ERROR_SUCCESS==m_reg.Open(HKEY_CURRENT_USER,"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",KEY_READ)) { ULONG m_ulsize1=1000; ULONG m_ulsize2=1000; m_reg.QueryStringValue("Desktop",DeskTop,&m_ulsize1); m_reg.QueryStringValue("AppData",AppData,&m_ulsize2); lstrcat(AppData,"\\Microsoft\\Internet Explorer\\Quick Launch"); } return 0; } //获取桌面文件夹的IShellFolder接口指针 BOOL CFileSearch::GetDesktopIShellFolder() { m_pIShellFolder=GetIShellFolderByPath(m_strDeskTopPath); //m_pAppData=GetIShellFolderByPath(m_strQuickLanchPath); return TRUE; } //获取桌面文件夹的IEnumIDList接口 //isQuickLanch---是否搜索第二层文件夹//isRecur---是否是文件夹BOOL CFileSearch::GetIEunmIDList(IShellFolder * pShellFolder,BOOL isRecur,BOOL isQuickLanch) { IEnumIDList *pIEnumFile = NULL ; IEnumIDList *pIEnumFolder = NULL ; if(!pShellFolder) return FALSE; HRESULT hr=pShellFolder->EnumObjects(0,SHCONTF_NONFOLDERS,&pIEnumFile); //不是文件夹 if(FAILED(hr)) { return FALSE; } if(!isRecur) { m_pFirstLayerFile = pIEnumFile; } EnumAllItems(pIEnumFile,FALSE,isQuickLanch); if(!isQuickLanch) { HRESULT hr=pShellFolder->EnumObjects(0,SHCONTF_FOLDERS,&pIEnumFolder); //文件夹 if(FAILED(hr)) { return FALSE; } if(!isRecur) { m_pFirstLayerFolder = pIEnumFolder; } EnumAllItems(pIEnumFolder,TRUE,isQuickLanch); } return TRUE; } BOOL CFileSearch::EnumAllItems(IEnumIDList *m_pEnum,BOOL isFolder,BOOL isQuickLanch) { LPITEMIDLIST m_pItem=NULL; ULONG m_ulwork= 0; while(m_pEnum->Next(1,&m_pItem,&m_ulwork)==S_OK) { //如果是第一层,重置路径 if(!isQuickLanch) { if((m_pFirstLayerFolder==m_pEnum) && (isFolder)) { lstrcpy(m_strParentPath,m_strDeskTopPath); } if((m_pFirstLayerFile==m_pEnum) && (!isFolder)) { lstrcpy(m_strParentPath,m_strDeskTopPath); } } else { // if((m_pFirstLayerFile==m_pEnum) && (!isFolder)) // { // lstrcpy(m_strParentPath,m_strQuickLanchPath); // } if((m_pFirstLayerFolder==m_pEnum) && (isFolder)) { lstrcpy(m_strParentPath,m_strDeskTopPath); } if((m_pFirstLayerFile==m_pEnum) && (!isFolder)) { lstrcpy(m_strParentPath,m_strDeskTopPath); } } WIN32_FIND_DATA ffd; SHGetDataFromIDList(m_pIShellFolder,m_pItem,SHGDFIL_FINDDATA,&ffd,sizeof(WIN32_FIND_DATA)); if(!isFolder) { CString m_strTempPath=m_strParentPath; m_strTempPath+="\\"; m_strTempPath += ffd.cFileName; CString m_strCmp=".lnk"; fprintf(fp,"%s\n",m_strTempPath.GetBuffer()); m_strTempPath.MakeUpper(); m_strCmp.MakeUpper(); if(m_strTempPath.Right(4)==m_strCmp) //判断是否是链接文件 { if (ReadShortCut(m_strTempPath.GetBuffer())) { string str = m_strTempPath.GetBuffer(); m_FindList.push_back(str); } m_strTempPath.ReleaseBuffer(); } } else { lstrcat(m_strParentPath,"\\"); lstrcat(m_strParentPath,ffd.cFileName); IShellFolder *m_pITemp=GetIShellFolderByPath(m_strParentPath); GetIEunmIDList(m_pITemp,TRUE,isQuickLanch); } } return TRUE; } //获取指定目录的IShellFolder接口 IShellFolder *CFileSearch::GetIShellFolderByPath(LPTSTR path) { IShellFolder *m_ShellFolderTopMost=NULL; HRESULT hr=SHGetDesktopFolder(&m_ShellFolderTopMost); if(FAILED(hr)) { return NULL; } IShellFolder *m_pFolder; LPITEMIDLIST pidlWorkDir=NULL; OLECHAR strOleFilePath[MAX_PATH]; MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, path, -1, strOleFilePath, MAX_PATH ); hr = m_ShellFolderTopMost->ParseDisplayName(NULL,NULL,strOleFilePath,NULL,&pidlWorkDir,NULL); if(FAILED(hr)) { return NULL; } hr=m_ShellFolderTopMost->BindToObject(pidlWorkDir,NULL,IID_IShellFolder,(LPVOID*)&m_pFolder); if(m_ShellFolderTopMost)m_ShellFolderTopMost->Release(); return m_pFolder; } //读取快捷方式的信息 BOOL CFileSearch::ReadShortCut(LPTSTR linkName) { ::CoInitialize(NULL); IShellLink *m_pIShellLink=NULL; IPersistFile *m_pIPersistFile=NULL; HRESULT hr=::CoCreateInstance(CLSID_ShellLink,NULL,CLSCTX_INPROC_SERVER,IID_IShellLink,(LPVOID*)&m_pIShellLink); if(hr==S_OK) { hr=m_pIShellLink->QueryInterface(IID_IPersistFile,(void **)&m_pIPersistFile); if(hr==S_OK) { USES_CONVERSION; m_pIPersistFile->Load(T2COLE(linkName),STGM_READWRITE); char m_strPath[MAX_PATH]={0}; m_pIShellLink->GetPath(m_strPath,MAX_PATH,NULL,SLGP_UNCPRIORITY); CString temp = m_strPath; temp.MakeUpper(); m_strFind.MakeUpper(); if (strstr(temp.GetBuffer(),m_strFind.GetBuffer())) //判断应用程序名 { //AfxMessageBox(temp); if(m_pIShellLink) m_pIShellLink->Release(); if(m_pIPersistFile) m_pIPersistFile->Release(); ::CoUninitialize(); return TRUE; } } } if(m_pIShellLink) m_pIShellLink->Release(); if(m_pIPersistFile) m_pIPersistFile->Release(); ::CoUninitialize(); return FALSE;
 
 
 
 
 
bool CModifyLinkICon::ChangeLinkIcon(const string& strLnkName,const string& strIconPath){    if (strLnkName.empty() || strIconPath.empty())    {        return false;    }    HRESULT hres;    IShellLink *psl = NULL;    IPersistFile *pPf = NULL;    int id;    LPITEMIDLIST pidl;    bool bRet = false;    do    {        hres = CoInitialize(NULL);        if (FAILED(hres))        {            break;        }        hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);        if (FAILED(hres))        {            break;        }        hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&pPf);        if (FAILED(hres))        {            break;        }        wchar_t wsz[256];        MultiByteToWideChar(CP_ACP, 0, strLnkName.c_str(), -1, wsz, MAX_PATH);        hres = pPf->Load(wsz, STGM_READWRITE);            if (FAILED(hres))        {            break;        }        hres = psl->SetIconLocation(strIconPath.c_str(), 0);        if (FAILED(hres))        {            break;        }        pPf->Save(wsz, TRUE);        if (FAILED(hres))        {            break;        }        bRet = true;    } while (0);    if (pPf != NULL)    {        pPf->Release();    }    if (psl != NULL)    {        psl->Release();    }    CoUninitialize();    AfxMessageBox("替换完成");    return bRet;}

 

4结论

其实这些操作估计很早之前就有,网上的信息页很多,我就算做一下汇总吧,最后给出我测试用的界面,很简答,可以实现快捷的搜索,快捷图标的更换,图像的读取,写入以及简单的修改。

转载于:https://www.cnblogs.com/zsb517/p/3491360.html

你可能感兴趣的文章
面试/编程
查看>>
linux每日命令(16):head命令
查看>>
公司内部分享【富有成效的每日站会】总结
查看>>
打造一个上传图片到图床利器的插件(Mac版 开源)
查看>>
iOS横竖屏
查看>>
thinkphp判断更新是否成功
查看>>
Do While ... Loop 与 Do Until ... Loop 的区别
查看>>
【Linux】查询某个字符串出现次数
查看>>
高效使用jquery之一:请使用'On'函数
查看>>
冲刺第一周第三天
查看>>
ERP环境检测工具设计与实现 Environment Detection
查看>>
不要在构造中做太多事情,不然有时候会出现有意思的代码~
查看>>
IIS 发布网站遇到的问题
查看>>
NuGet学习笔记(2)——使用图形化界面打包自己的类库
查看>>
xcode中没有autoSizing的设置
查看>>
字符编码
查看>>
企业应用:应用层查询接口设计
查看>>
浅谈Excel开发:十 Excel 开发中与线程相关的若干问题
查看>>
nfd指令的详细说明
查看>>
安装VisualSvn Server时遇到的问题
查看>>