I have an application with a tool bar and an Image Collection. The problem is that I do not have the original images and I need to create another tool bar with some of the same buttons. Is there a way to save the Images Collection from the tool bar to a file?
I tried extracting the images from a resource file but I do not know which one has the images stored in.
Although I did not find an answer for my question, I managed to get the images by reading the tool bar image list and saving each one to a file according to the given image key.
for (int x = 0; x < this.imageListToolbar3small.Images.Count; ++x)
{
Image temp = this.imageListToolbar.Images[x];
temp.Save(this.imageListToolbar.Images.Keys[x] + ".png");
}
This came from an answer to this question: How to Export Images from an Image List in VS2005?
I just added the code after the InitializeComponent call and saved all images in debug mode. I did not needed to run the full application.
If anyone does have a better idea or a small application to retrieve images from a tool bar using only the resource file, that would be appreciated. I will not mark as an answer since it is more a workaround.
I use this approach:
foreach (ToolBarButton b in toolBar.Buttons)
{
//can be negative, for separators, because separators don't have images
if (b.ImageIndex >= 0)
{
Image i = toolBar.ImageList.Images[b.ImageIndex];
i.Save(b.ImageIndex + ".png");
}
}
I needed to recover images from a private ImageList member of a Control. I used the following code (Sorry, it's VB but s/b easy to refactor)
Dim cntrl = New TheClassWithThePrivateImageList
Dim pi As Reflection.PropertyInfo, iml As System.Windows.Forms.ImageList, propName = "ThePropertyName"
pi = cntrl.GetType.GetProperty(propName, Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance)
iml = CType(pi.GetValue(cntrl), System.Windows.Forms.ImageList)
For Each key In iml.Images.Keys
Dim image As Drawing.Image = iml.Images.Item(key)
image.Save($"{propName}_{key}")
Next
Related
I'm trying to find a good way to load say 100+ small images (98px png's each) into my .net form and additionally have them all interactive in a way (click, and a name of the image/file), but without loading the images from a local predefined folder. What do I mean by that? Let me explain and demonstrate an example. Please bear with me, I'm kinda confused on the topic of building the solution and compiling the executeable's folder structure.
Example:
Imagine when creating a profile on say, here for example. Usually, you set a name and add a profile picture. Sometimes the profile picture has to be uploaded, but in my case I want to have a preset of 100 available profile pictures that the user can choose from. It may sound like a lot, but considering the purpose of the application it really is nesseary.
The problem/question:
The easy and probably not so good way is simply adding pictureboxes and assigning a click to them onto a flowlayoutpanel. This is my current temporary solution, but the big flaw is that it uses a locally stored path. This app is supposed to installed on several machines and I need this to work on whichever computer it's installed on, no matter what drive letter that is used ect.
string[] files = Directory.GetFiles("C:\\path\\folder_a", "*", SearchOption.TopDirectoryOnly);
foreach (var filename in files)
{
Bitmap bmp = null;
try
{
bmp = new Bitmap(filename);
}catch{
}
var card = new PictureBox();
card.BackgroundImage = bmp;
card.Tag = (filename.Split('\\').Last());
card.Padding = new Padding(0);
card.BackgroundImageLayout = ImageLayout.Stretch;
card.Size = normal;
card.Click += delegate
{
//something
};
flowProfileIcons.Controls.Add(card);
}
These are the options to my knownledge, but I don't really know:
Embed (in 'build action') all the images directly from a folder within solution explorer and use AssemblyDirectory to find and use the images in a similar way as displayed above. However, will this allow the users to actually access and potentionally modify/delete the files because they are exposed in the installation folder? And is this even a good way to do this?
Put all images in resources.resx and somehow use the images from there, but as far as I've seen that isn't very easy to do. I will definitely look into it though if this is the prefered way. I did try some things out and this is my progress so far, though just testing - not working.
var images = Properties.resProfileIconsDark.ResourceManager
.GetResourceSet(CultureInfo.CurrentCulture, true, true)
.Cast<DictionaryEntry>()
.Where(x => x.Value.GetType() == typeof(Bitmap))
.Select(x => new { Name = x.Key.ToString(), Image = x.Value })
.ToList();
This is where I'm at. Hopefully someone can push me in the right direction.
I am trying to build a PowerPoint add-in that will allow me to do a one-click optimization of the current presentation by removing unused master slides and converting huge 24-bit PNG files to slightly-compressed JPGs.
I have the first part handled already, and now I'm working on the images. Although I can easily find the Shape object containing the image, I cannot find a way to access the source image through the managed API. At best, I can copy the shape to the clipboard, which does give me the image but in a different format (MemoryBmp).
using PPTX = Microsoft.Office.Interop.PowerPoint;
...
foreach (PPTX.Slide slide in Globals.ThisAddIn.Application.ActivePresentation.Slides)
{
foreach (PPTX.Shape shape in slide.Shapes)
{
if (shape.Type == MsoShapeType.msoPicture)
{
// Now, how can I access the source image contained within this shape?
// I -can- copy it via the clipboard, like this:
shape.Copy();
System.Drawing.Image image = Clipboard.GetImage();
// ...but image's format reflects a MemoryBmp ImageFormat, as noted here:
// https://referencesource.microsoft.com/#System.Drawing/commonui/System/Drawing/Advanced/ImageFormat.cs
// ...which doesn't help me determine if the source image is something that should be optimized.
}
}
}
Obviously, I can get to the images directly via other methods (e.g. accessing the contents of the file as a ZIP, or using OpenXML SDK), but I'm trying to perform all the steps from within the already-opened presentation (which means I can't update the open file). Any thoughts on how I can do this?
You could use a Microsoft.Office.Interop.PowerPoint.Shape Export function.
void Export(string PathName, PpShapeFormat Filter, int ScaleWidth = 0, int ScaleHeight = 0, PpExportMode ExportMode = PpExportMode.ppRelativeToSlide)
There is a very little documentation of this function.
I've found it in the Shape interface definition.
So your code would look something like:
shape.Export(<some_file>, PpShapeFormat.ppShapeFormatPNG);
More info on MSDN
I'm working on a windows service in c# 4.0 wich transform different file in image (tif and jpeg)
I have a problem when i want to convert a html file (usually an e-mail) in image.
I use WebBrowser
var browser = new WebBrowser();
browser.DocumentCompleted += this.BrowserDocumentCompleted;
browser.DocumentText = html;
and DrawToBitmap
var browser = sender as WebBrowser;
Rectangle body = new Rectangle(browser.Document.Body.ScrollRectangle.X * scaleFactor,
browser.Document.Body.ScrollRectangle.Y * scaleFactor,
browser.Document.Body.ScrollRectangle.Width * scaleFactor,
browser.Document.Body.ScrollRectangle.Height * scaleFactor);
browser.Height = body.Height;
Bitmap output = new Bitmap(body.Width, body.Height);
browser.DrawToBitmap(output, body);
It works fine for small or medium html, but with long html (like 22 000 height px or more)
I have GDI exeptions on DrawToBitmap :
Invalid parameter
Not an image GDI+ valid
According to internet, this kind of error append because the image is too big.
My question : How can i convert html in X images (pagination) without generate the big image and crop after, and if it's possible without using library.
Thank you in advance.
Edit : I found a tricky solution : surround the html with a div witch gonna set the page and another for the offset, for exemple :
<div style="height:3000px; overflow:hidden">
<div style="margin-top:-3000px">
But this solution can crop on a line of text or in the middle of an image...
You can try creating a custom IE Print Template and use DEVICERECT and LAYOUTRECT elements to drive the pagination. The lines wouldn't get cut in the middle then, and you'd capture a bitmap of each DEVICERECT as a page. You'd need to issue CGID_MSHTML/IDM_SETPRINTTEMPLATE command to MSHTML document object (webBrowser.Document.DomDocument as IOleCommandTarget) to enable the Print Template-specific element tags like those. More information about Print Templates can be found here.
[EDITED] You can even use IHTMLElementRender::DrawToDC API on a DEVICERECT object to draw its content on a bitmap DC. You'd need to enable FEATURE_IVIEWOBJECTDRAW_DMLT9_WITH_GDI and disable FEATURE_GPU_RENDERING feature control settings for your WebBrowser hosting app to use IHTMLElementRender::DrawToDC.
Thank you for your anwser Noseratio.
I founded a solution by using printing and a virtual printer to get image file.
Save the html in a file and remove all encoding :
html = Regex.Replace(html, "<meta[^>]*http-equiv=\"Content-Type\"[^>]*>", string.Empty, RegexOptions.Multiline);
using (var f = File.Create(filePath))
{
var bytes = Encoding.Default.GetBytes(html);
f.Write(bytes, 0, bytes.Length);
}
Run the print without show the webbrowser and printing popup :
const short PRINT_WAITFORCOMPLETION = 2;
const int OLECMDID_PRINT = 6;
const int OLECMDEXECOPT_DONTPROMPTUSER = 2;
dynamic ie = browser.ActiveXInstance;
ie.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER, PRINT_WAITFORCOMPLETION);
I use PDFCreator for virtual printing and it keep me all files in a folder. It's not easy to get all of this file (know when printing is finish, how many files and when you can use them...) but it isn't the purpose of this post!
I'm currently doing the below to add an image to an excel file I'm creating via "interop"
private Excel.Workbook _xlWorkBook;
_xlWorkSheet.Shapes.AddPicture(appPath + #"\ImageFile.png", Microsoft.Office.Core.MsoTriState.msoFalse, Microsoft.Office.Core.MsoTriState.msoCTrue, 5, 5, 60, 60);
I have a couple of questions if I may.
How can I access the picture once it's added - e.g. to draw a border on it.
Doing the above for my app means that I have to distribute the image file as well so I thought I would put it in the application resources. How do I add the image from the resources to the excel file? Again once added, how do I access it to add border etc?
_xlWorkSheet.Shapes.AddPicture(Properties.Resources.ImageFile); //dosn't work
Many thanks
1.) I believe you can access the picture by using
// after adding the picture
Picture pic = (Picture) ActiveSheet.Pictures(ActiveSheet.Pictures.Count - 1);
pic.Border.LineStyle = XlLineStyle.xlContinuous;
pic.Border.Weight = XlBorderWeight.xlMedium;
Or
// add the picture using Pictures.Insert
// this should return a Picture cast-able object
Picture pic = (Picture) ActiveSheet.Pictures.Insert(FileName);
// etc...
2.) The simplest way would be to pull the file from resources write it to a temp file, add it into excel and then remove the temp file.
This code is very much untested. Excel interop is a head-ache.
Sorry or the archeology.
For the second question, adding a picture from a ressource, I may have found a solution using the clipboard:
System.Drawing.Bitmap pic = Properties.Resources.my_ressource;
System.Windows.Forms.Clipboard.SetImage(pic);
Range position = (Range)myWorksheet.Cells[Y, X];
myWorksheet.Paste(position); //copy the clipboard to the given position
RE: 2. I did this:
S = Shapes.AddPicture(filename,MsoTriState.msoFalse,MsoTriState.msoTrue,0,0,50,50);
S.Name = "Picture";
S.Placement = XlPlacement.xlMoveAndSize;
I've got the following code
files = di.GetFiles("*.jpg");
for (int i = 0; i < files.Length; i++)
{
il.Images.Add(System.Drawing.Image.FromFile(folder + "\\" + files[i].Name));
lv.Items.Add(files[i].Name, i);
}
the code fills a System.Windows.Forms.ImageList with pictures from a jpg files.
it also creates a System.Windows.Forms.ListView where each item is associated with a picture in the imagelist.
I made the files small and tried to optimize the code. Yet I cant get under 3 seconds for 290 ~30k jpg files(or any other format).
Do you have a better way to load the list view?
Wrap your code in BeginUpdate / EndUpdate calls for the ListView.
One simple change you could make is to change this:
folder + "\\" + files[i].Name
to this:
files[i].FullName
You can also use a foreach loop instead of a for loop:
foreach (FileInfo file in files)
{
il.Images.Add(System.Drawing.Image.FromFile(file.FullName));
lv.Items.Add(file.Name, i);
}
And a ListView can work in either bound or unbound mode. You are using unbound mode. Sometimes it is cleaner to use bound mode.