#include "headers.h" #pragma pack(push, 1) 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; typedef struct { WORD idReserved; // Reserved (must be 0) WORD idType; // Resource Type (1 for icons) WORD idCount; // How many images? ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em) } ICONDIR, *LPICONDIR; #pragma pack(pop) static void SaveIconToFile(HICON hIcon, TCHAR *szFile) { ICONINFO iconInfo = {0}; BITMAP bmpColor, bmpMask; HANDLE hFile = 0; HANDLE hMap = 0; BYTE *pFile = 0; GetIconInfo(hIcon, &iconInfo); GetObject(iconInfo.hbmColor, sizeof(bmpColor), &bmpColor); GetObject(iconInfo.hbmMask, sizeof(bmpMask), &bmpMask); do { if (bmpColor.bmBitsPixel <= 8) break; DWORD dwColorSize = bmpColor.bmWidthBytes * bmpColor.bmHeight; DWORD dwMaskSize = bmpMask.bmWidthBytes * bmpMask.bmHeight; DWORD dwFileSize = sizeof(ICONDIR) + sizeof(BITMAPINFOHEADER) + dwColorSize + dwMaskSize; hFile = CreateFile(szFile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) break; hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, dwFileSize, NULL); if (!hMap) break; pFile = (BYTE *)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0 ,0); if (!pFile) break; ICONDIR iconDir = {0}; iconDir.idCount = 1; iconDir.idType = 1; iconDir.idEntries[0].bWidth = bmpColor.bmWidth; iconDir.idEntries[0].bHeight = bmpColor.bmHeight; iconDir.idEntries[0].bColorCount = 0; iconDir.idEntries[0].wPlanes = bmpColor.bmPlanes; iconDir.idEntries[0].wBitCount = bmpColor.bmBitsPixel; iconDir.idEntries[0].dwBytesInRes = sizeof(BITMAPINFOHEADER) + dwColorSize + dwMaskSize; iconDir.idEntries[0].dwImageOffset = sizeof(ICONDIR); MoveMemory(pFile, &iconDir, sizeof(ICONDIR)); BITMAPINFOHEADER iconBmp = {0}; iconBmp.biSize = sizeof(iconBmp); iconBmp.biWidth = bmpColor.bmWidth; iconBmp.biHeight = bmpColor.bmHeight + bmpMask.bmHeight; iconBmp.biPlanes = bmpColor.bmPlanes; iconBmp.biBitCount = bmpColor.bmBitsPixel; iconBmp.biSizeImage = dwColorSize + dwMaskSize; MoveMemory(pFile + sizeof(ICONDIR), &iconBmp, sizeof(BITMAPINFOHEADER)); BYTE *buf = (BYTE *)mir_alloc(dwColorSize); GetBitmapBits(iconInfo.hbmColor, dwColorSize, buf); for (int row = 0; row < bmpColor.bmHeight; ++row) { MoveMemory( pFile + sizeof(ICONDIR) + sizeof(BITMAPINFOHEADER) + row * bmpColor.bmWidthBytes, buf + (bmpColor.bmHeight - row - 1) * bmpColor.bmWidthBytes, bmpColor.bmWidthBytes); } mir_free(buf); GetBitmapBits(iconInfo.hbmMask, dwMaskSize, pFile + sizeof(ICONDIR) + sizeof(BITMAPINFOHEADER) + dwColorSize); } while(0); DeleteObject(iconInfo.hbmColor); DeleteObject(iconInfo.hbmMask); if (pFile) UnmapViewOfFile(pFile); if (hMap) CloseHandle(hMap); if (hFile && hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); } CJumpListArray::CJumpListArray() { CoCreateInstance(CLSID_EnumerableObjectCollection, NULL, CLSCTX_INPROC_SERVER, IID_IObjectCollection, (void **)&m_pObjects); } CJumpListArray::~CJumpListArray() { if (m_pObjects) m_pObjects->Release(); } void CJumpListArray::AddItemImpl(TCHAR *icon, int iIcon, TCHAR *title, TCHAR *path, TCHAR *args) { IShellLink *link = NewShellLink(icon, iIcon, title, path, args); m_pObjects->AddObject(link); link->Release(); } void CJumpListArray::AddItem(char *mir_icon, TCHAR *title, TCHAR *path, TCHAR *args) { TCHAR icon[MAX_PATH]; int iIcon; LoadMirandaIcon(mir_icon, icon, &iIcon); AddItemImpl(icon, iIcon, title, path, args); } void CJumpListArray::AddItem(int skinicon, TCHAR *title, TCHAR *path, TCHAR *args) { TCHAR icon[MAX_PATH]; int iIcon; LoadMirandaIcon(skinicon, icon, &iIcon); AddItemImpl(icon, iIcon, title, path, args); } void CJumpListArray::AddItem(char *proto, int status, TCHAR *title, TCHAR *path, TCHAR *args) { TCHAR icon[MAX_PATH]; int iIcon; LoadMirandaIcon(proto, status, icon, &iIcon); AddItemImpl(icon, iIcon, title, path, args); } IObjectArray *CJumpListArray::GetArray() { IObjectArray *result = NULL; m_pObjects->QueryInterface(IID_IObjectArray, (void **)&result); return result; } bool CJumpListArray::LoadMirandaIcon(char *mir_icon, TCHAR *icon, int *id) { *id = 0; TCHAR *path = Utils_ReplaceVarsT(_T("%miranda_userdata%\\w7ui.IconCache")); CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)path); TCHAR *name = mir_a2t(mir_icon); for (TCHAR *ch = name; *ch; ++ch) if (_tcschr(_T("\\/:*?<>|"), *ch)) *ch = _T('_'); mir_sntprintf(icon, MAX_PATH, _T("%s\\%s.ico"), path, name); mir_free(name); mir_free(path); HICON hIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)mir_icon); SaveIconToFile(hIcon, icon); return true; } bool CJumpListArray::LoadMirandaIcon(int skinicon, TCHAR *icon, int *id) { *id = 0; TCHAR *path = Utils_ReplaceVarsT(_T("%miranda_userdata%\\w7ui.IconCache")); CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)path); mir_sntprintf(icon, MAX_PATH, _T("%s\\skinicon$%d.ico"), path, skinicon); mir_free(path); HICON hIcon = LoadSkinnedIcon(skinicon); SaveIconToFile(hIcon, icon); return true; } bool CJumpListArray::LoadMirandaIcon(char *proto, int status, TCHAR *icon, int *id) { *id = 0; TCHAR *path = Utils_ReplaceVarsT(_T("%miranda_userdata%\\w7ui.IconCache")); CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)path); mir_sntprintf(icon, MAX_PATH, _T("%s\\skinprotoicon$") _T(TCHAR_STR_PARAM) _T("$%d.ico"), path, proto, status); mir_free(path); HICON hIcon = LoadSkinnedProtoIcon(proto, status); SaveIconToFile(hIcon, icon); return true; } IShellLink *CJumpListArray::NewShellLink(TCHAR *icon, int iIcon, TCHAR *title, TCHAR *path, TCHAR *args) { IShellLink *pShellLink = NULL; CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&pShellLink); pShellLink->SetPath(path); pShellLink->SetIconLocation(icon, iIcon); pShellLink->SetArguments(args); pShellLink->SetShowCmd(SW_SHOWDEFAULT); IPropertyStore *pPropStore = NULL; if (SUCCEEDED(pShellLink->QueryInterface(IID_IPropertyStore, (void **)&pPropStore))) { PROPVARIANT pv; InitPropVariantFromString(title, &pv); pPropStore->SetValue(PKEY_Title, pv); PropVariantClear(&pv); pPropStore->Commit(); pPropStore->Release(); } return pShellLink; }