ICON文件保存

这两天想做一下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<string>* 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结论

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

1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值