private void createIconResources(ResImageGroupData idata, byte[] iconbytes) { //now we've re-created the .ico file as a memory stream //extract each icon from it by the icon dimensions from the data directory MemoryStream ms = new MemoryStream(iconbytes); ResData image = null; for (int i = 0; i < idata.entries.Count; i++) { ResImageGroupDataEntry ientry = idata.entries[i]; ms.Position = 0; Icon iconRes = new Icon(ms, (int)ientry.bWidth, (int)ientry.bHeight); //get the icon ientry.image = iconRes; //link it to this res obj foreach (ResData imagedata in iconItems) { if (imagedata.id == ientry.nID) { image = imagedata; break; } } //and add it to the ICON resource list as well if (image != null) { addIcon(image.id, image.name, image.lang, iconRes); getDataItem(icons, image.id, image.name).getItem(image.lang).dataBuf = image.data; } } }
private void createCursorResources(ResImageGroupData idata, byte[] cursorbytes, int entrynum) { //get the cursor image from the .ico file we've created in memory MemoryStream ms = new MemoryStream(cursorbytes); ms.Position = 0; Icon curRes = new Icon(ms); //get the cursor ResImageGroupDataEntry ientry = idata.entries[entrynum]; ientry.image = curRes; //link it to this res obj ResData image = null; foreach (ResData curdata in cursorItems) { if (curdata.id == ientry.nID) { image = curdata; break; } } //and add it to the CUSROR resource list as well if (image != null) { addCursor(image.id, image.name, image.lang, curRes); getDataItem(cursors, image.id, image.name).getItem(image.lang).dataBuf = image.data; } }
//- icon loading -------------------------------------------------------------- //we create an .ico file in memory for icon resources private byte[] buildIconFile(ResImageGroupData idata) { //build .ico file header byte[] hdrbytes = { 0, 0, 1, 0, 0, 0 }; hdrbytes[4] = (byte)(idata.entries.Count % 0x100); hdrbytes[5] = (byte)(idata.entries.Count / 0x100); //build .ico data directory int datapos = 6 + (0x10 * idata.entries.Count); byte[] dirbytes = new byte[0x10 * idata.entries.Count]; int dirpos = 0; for (int i = 0; i < idata.entries.Count; i++) { ResImageGroupDataEntry ientry = idata.entries[i]; dirbytes[dirpos++] = (byte)ientry.bWidth; dirbytes[dirpos++] = (byte)ientry.bHeight; dirbytes[dirpos++] = (byte)ientry.bColorCount; dirbytes[dirpos++] = 0; dirbytes[dirpos++] = (byte)(ientry.wPlanes % 0x100); dirbytes[dirpos++] = (byte)(ientry.wPlanes / 0x100); dirbytes[dirpos++] = (byte)(ientry.wBitCount % 0x100); dirbytes[dirpos++] = (byte)(ientry.wBitCount / 0x100); byte[] sizebytes = BitConverter.GetBytes(ientry.dwBytesInRes); Array.Copy(sizebytes, 0, dirbytes, dirpos, 4); byte[] posbytes = BitConverter.GetBytes(datapos); Array.Copy(posbytes, 0, dirbytes, dirpos + 4, 4); dirpos += 8; datapos += (int)ientry.dwBytesInRes; } byte[] iconbytes = new byte[datapos]; //total .ico data buf Array.Copy(hdrbytes, 0, iconbytes, 0, 6); Array.Copy(dirbytes, 0, iconbytes, 6, dirbytes.Length); //copy the .ico header to it //append icon data for each icon in directory datapos = 6 + (0x10 * idata.entries.Count); ResData image = null; for (int i = 0; i < idata.entries.Count; i++) { ResImageGroupDataEntry ientry = idata.entries[i]; foreach (ResData imagedata in iconItems) //find the matching icon data { if (imagedata.id == ientry.nID) { image = imagedata; break; } } if (image != null) { Array.Copy(image.data, 0, iconbytes, datapos, image.data.Length); //and add it to the data buf datapos += image.data.Length; } } return(iconbytes); }
//----------------------------------------------------------------------------- public void addIconGroup(uint id, String name, uint language, ResImageGroupData item) { ResIconGroup ig = (ResIconGroup)getDataItem(iconGroups, id, name); if (ig == null) { ig = new ResIconGroup(id, name); iconGroups.Add(ig); } ig.addItem(language, item); }
//----------------------------------------------------------------------------- public void addCursorGroup(uint id, String name, uint language, ResImageGroupData item) { ResCursorGroup cg = (ResCursorGroup)getDataItem(cursorGroups, id, name); if (cg == null) { cg = new ResCursorGroup(id, name); cursorGroups.Add(cg); } cg.addItem(language, item); }
//like bmp files (see below) we build an .ico file in memory, and then create an Icon obj from it //the complication here is (unlike bitmap resources) the data is split between ICON and ICONGROUP resources //so we've stored all the ICON resource data while parsing the resource data & now join head to body private void parseIconGroups() { foreach (ResIconGroup ig in iconGroups) { foreach (ResourceItem item in ig.items) { ResImageGroupData idata = (ResImageGroupData)item.item; //this contains the .ico file header data byte[] iconbytes = buildIconFile(idata); //build .ico file from header & saved icon data createIconResources(idata, iconbytes); //extract images from .ico file & add to icon list } } icons.Sort(); }
//- cursor loading ------------------------------------------------------------ //the C# Cursor class is limited for displaying as an image, so we use an Icon obj instead //we create an .ico file in memory for cursor resources private byte[] buildCursorFile(ResImageGroupData idata, int entrynum) { //build .ico file header byte[] hdrbytes = { 0, 0, 1, 0, 1, 0 }; //build .ico data directory for a single cursor resource int datapos = 0x16; byte[] dirbytes = new byte[0x10]; int dirpos = 0; ResImageGroupDataEntry ientry = idata.entries[entrynum]; dirbytes[dirpos++] = (byte)ientry.bWidth; dirbytes[dirpos++] = (byte)ientry.bWidth; //square icon dirbytes[dirpos++] = 2; //monochrome dirbytes[dirpos++] = 0; dirbytes[dirpos++] = 1; dirbytes[dirpos++] = 0; dirbytes[dirpos++] = 1; dirbytes[dirpos++] = 0; uint bsize = ientry.dwBytesInRes - 4; byte[] sizebytes = BitConverter.GetBytes(bsize); Array.Copy(sizebytes, 0, dirbytes, dirpos, 4); byte[] posbytes = BitConverter.GetBytes(datapos); Array.Copy(posbytes, 0, dirbytes, dirpos + 4, 4); dirpos += 8; datapos += (int)ientry.dwBytesInRes; byte[] cursorbytes = new byte[datapos]; //total .cur data buf Array.Copy(hdrbytes, 0, cursorbytes, 0, 6); Array.Copy(dirbytes, 0, cursorbytes, 6, 0x10); //copy the .cur header to it //append cursor data for each icon in directory ResData image = null; foreach (ResData imagedata in cursorItems) //find the matching cursor data { if (imagedata.id == ientry.nID) { image = imagedata; break; } } if (image != null) { Array.Copy(image.data, 4, cursorbytes, 0x16, image.data.Length - 4); //and add it to the data buf, skip the hotspot bytes } return(cursorbytes); }
private void parseCursorGroups() { foreach (ResCursorGroup cg in cursorGroups) { foreach (ResourceItem item in cg.items) { ResImageGroupData idata = (ResImageGroupData)item.item; //this contains the .cur file header data for (int i = 0; i < idata.entries.Count; i++) { byte[] cursorbytes = buildCursorFile(idata, i); //build .ico file from header & saved cursor data createCursorResources(idata, cursorbytes, i); //extract images from .ico file & add to icon list } } } cursors.Sort(); }
public static ResImageGroupData parseData(byte[] resdata) { ResImageGroupData igdata = new ResImageGroupData(); SourceFile src = new SourceFile(resdata); uint res = src.getTwo(); uint type = src.getTwo(); int count = (int)src.getTwo(); igdata.entries = new List <ResImageGroupDataEntry>(count); for (int i = 0; i < count; i++) { ResImageGroupDataEntry igentry = ResImageGroupDataEntry.parseData(src); igdata.entries.Add(igentry); } return(igdata); }
//leaf node of resource directory tree, this rec points to actual data private void parseResourceData(SourceFile source) { uint datapos = source.getFour(); uint datasize = source.getFour(); uint codepage = source.getFour(); uint reserved = source.getFour(); datapos -= resourceRVA; byte[] resdata = source.getRange(datapos, datasize); //get resource data //get the store type/id/lang vals we stored in our decent to this node uint restype = resIdNameValues[0]; uint resid = resIdNameValues[1]; String resname = (resid >= 0x80000000) ? getResourceName(source, resid) : null; uint reslang = resIdNameValues[2]; switch (restype) { case 1: ResData curdata = new ResData(resid, resname, reslang, resdata); cursorItems.Add(curdata); break; case 2: Bitmap bmp = ResBitmap.parseData(resdata); addBitmap(resid, resname, reslang, bmp); getDataItem(bitmaps, resid, resname).getItem(reslang).dataBuf = resdata; break; case 3: ResData icondata = new ResData(resid, resname, reslang, resdata); iconItems.Add(icondata); break; case 4: addMenu(resid, resname, reslang, resdata); //List<String> menu = ResMenu.parseData(resdata); //addMenu(resid, resname, reslang, menu); getDataItem(menus, resid, resname).getItem(reslang).dataBuf = resdata; break; case 5: addDialog(resid, resname, reslang, resdata); //List<String> dlg = ResDialog.parseData(resdata); //addDialog(resid, resname, reslang, dlg); getDataItem(dialogs, resid, resname).getItem(reslang).dataBuf = resdata; break; case 6: List <String> strings = ResStringTable.parseData(resdata); addStringTable(resid, resname, reslang, strings); getDataItem(stringtable, resid, resname).getItem(reslang).dataBuf = resdata; break; case 7: addFontDirectory(resid, resname, reslang, resdata); getDataItem(fontDirectories, resid, resname).getItem(reslang).dataBuf = resdata; break; case 8: addFont(resid, resname, reslang, resdata); getDataItem(fonts, resid, resname).getItem(reslang).dataBuf = resdata; break; case 9: List <String> accel = ResAccelerator.parseData(resdata); addAccelerator(resid, resname, reslang, accel); getDataItem(accelerators, resid, resname).getItem(reslang).dataBuf = resdata; break; case 10: addUserData(resid, resname, reslang, resdata); getDataItem(userData, resid, resname).getItem(reslang).dataBuf = resdata; break; case 12: ResImageGroupData cg = ResImageGroupData.parseData(resdata); addCursorGroup(resid, resname, reslang, cg); getDataItem(cursorGroups, resid, resname).getItem(reslang).dataBuf = resdata; break; case 14: ResImageGroupData ig = ResImageGroupData.parseData(resdata); addIconGroup(resid, resname, reslang, ig); getDataItem(iconGroups, resid, resname).getItem(reslang).dataBuf = resdata; break; case 16: addVersion(resid, resname, reslang, resdata); //List<String> version = ResVersion.parseData(resdata); //addVersion(resid, resname, reslang, version); getDataItem(versions, resid, resname).getItem(reslang).dataBuf = resdata; break; default: addUserData(resid, resname, reslang, resdata); getDataItem(userData, resid, resname).getItem(reslang).dataBuf = resdata; break; } }