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.
Related
I am working on a music player for pc using c# and all seems to go fine but, i have problem in loading all the music files from the music directory because it loads very slowly and this take time when opening the app, it could take 5 min depending on the amount of music files. I think this happens because i created a loop to loop through each music file and get the metadatas and also the picture to load on different picture boxes for each music file.
Please Help, i need it to be faster. Thank you.
the code is below...
public List<MusicDetails> Music_Library()
{
List<MusicDetails> files = new List<MusicDetails>();
string[] musicfolder = Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.MyMusic),"*mp3", SearchOption.AllDirectories);
for (int i = 0; i <musicfolder.Length; i++)
{
try {
files.Add(new MusicDetails
{
title = TagLib.File.Create(musicfolder[i]).Tag.Title,
genre = TagLib.File.Create(musicfolder[i]).Tag.FirstGenre,
artist = TagLib.File.Create(musicfolder[i]).Tag.FirstPerformer,
path = musicfolder[i],
CoverArt = OrganiseAlbums.SingleAlbumImage(musicfolder[i],true)
});
}catch(Exception)
{
// OMIT FILE
}
}
return files;
}
You could try replacing your loop with a parallel foreach loop using background threads - add each item to the UI as it is processed, and let .Net determine the most efficient way to process everything. If you do it right, your UI will remain responsive, and your users will start out with "enough to look at..." Here is a link to get you started:
https://msdn.microsoft.com/en-us/library/dd460720(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
If you have a ton of music files, though, you may not want to load them all into memory at once. I would look into some sort of a list control or layout control that allows virtualization so that you instantiate and display only the visible ones at any given time. Use a tutorial to see how to bind to your collection so that it is virtualized.
If you post a more specific question with examples of what you have tried, you will get more specific answers...
Windows Forms - VSTO - Outlook
Background - I am creating a digital archive add-in for Office where the user can search the database for the client (whom the document belongs to) and it will save the file to the appropriate folder(s) based on the nature of the file. So far this is working for Word as planned but I am now using Outlook which has more to consider (attachments, message body, etc.).
I have got it working so far that the attachments are saved into a temporary folder (which is emptied each time the windows form closes) ready to be sorted and I can obtain information about sender/subject/email body. The list of attachments is set out into a CheckedListBox
Current Problem - When a user is looking to archive an attachment (a lot of documents/scanned documents will come up), images will be confusing as they may be necessary or entirely unimportant so I wish to preview the images.
I am trying to get it so on the event of
private void chkAttachments_SelectedValueChanged(object sender, EventArgs e)
The image shows in picAttachPreview (PictureBox) as a preview of that file. This will be taking the image from tempfolder (#"c:\temp\DigitalArchive").
I understand this is wrong but I am trying to set the source for the image shown on screen on that SelectedValueChanged event.
My [Incorrect] Code -
if(chkAttachments.Text.Contains(".jpg"))
{
var selectedImage = chkAttachments.SelectedValue.ToString();
picAttachPreview.Image = tempfolder + #"\" + selectedImage; //(A)
}
The (A) line is the issue and although I understand why, I don't know how to resolve it. The filepath is constructed with tempfolder and selectedImage (e.g. ScannedDoc.jpg) but the file path type is String but picAttachPreview is System.Drawing.Image so I assume I am looking at the wrong property of picAttachPreview to set the source of the image.
Any help or guidance will be immensely appreciated. Thank you.
(Also if you know of any good way I can set the same nature of preview for documents/PDF then I will be immensely grateful)
Edit Although the link solves part of my problem, there is an issue with chkAttachments.SelectedValue.ToString() which I answered below. (If anyone can advise me on the site etiquette for this situation. Do I delete the question or leave it with the answer I found so that people can find the solution to the same problem in future? Thank you)
After some playing around, I found another problem (chkAttachment.Text works whereas .SelectedValue.ToString() does not.
Also the issue with the string to image format is resolved by prefixing the path with Image.FromFile(
So the correct way of changing the image upon selection is:
if(chkAttachments.Text.Contains(".jpg"))
{
var selectedImage = chkAttachments.Text;
picAttachPreview.Image = Image.FromFile(tempfolder + #"\" + selectedImage);
}
Originally I started having the images put into a database and using generic handler to view the images, it was ok for one part of my app but then I realized that storing images in the database wasn't going to work out to well for a part of my application because I will be dynamically creating an html table with hyperlinks and using images for hyperlinks.
So using generic handlers would see to be a huge mess when creating the html and navigation hyperlinks,
So what I have opted to do is now is put these images to a folder on the server, but right now I am using my laptop before I even get to the point of publishing the app on line.
So this is the code I am using...
string iconName = fpIcon.FileName;
string iconExtension = Path.GetExtension(iconName);
string iconMimeType = fpIcon.PostedFile.ContentType;
string[] matchExtension = { ".jpg", ".png", ".gif" };
string[] matchMimeType = { "image/jpeg", "image/png", "image/gif" };
if (fpIcon.HasFile)
{
if (matchExtension.Contains(iconExtension) && matchMimeType.Contains(iconMimeType))
{
fpIcon.SaveAs(Server.MapPath(#"~/Images/" + iconName));
Image1.ImageUrl = #"~/Images/" + iconName;
}
}
So my question is, and don't laugh to hard but, where are these images being stored? I can't find them anywhere on my laptop using the windows search. With all the images that I have in this ~/Images directory, I can change the image to any image I wanted by supplying the name, but I have no idea where the images are being held, and when I do deploy to a site then where are they going to be then?
Thanks
Server.MapPath gives your current website directory(IIS hosted or running from VS). So go to your website directory, find Images directory there and you'll see your images.
This question already exists:
Closed 10 years ago.
Possible Duplicate:
how to populate a listbox with files in the project of my windows phone 7 application
I'm a newbie on C# and this is annoying me a lot.
My application load a set of images from a folder that I simply created on the Solution Explorer called Images. I can see these images if I use it hardcoded with URIs and stuff, but what I want to do is to take these images names dinamycally and then load it. I have seen some questions like it but couldnt solve my problem. I'm trying like this:
DirectoryInfo directoryInfo = new DirectoryInfo(#"/Images");
foreach (FileInfo file in directoryInfo.GetFiles()) {
photos.Add(new Photo() { FileName = file.FullName, PhotoSource = GetImageSource("Images/" + file.FullName) });
}
The directoryInfo is always set as null. My project hierarchy as shown in Solution Explorer is like:
Project
Main.xaml
Maim.xaml.cs
Images
1.jpg
2.jpg
...
Thanks in any help.
From MSDN:
For a Windows Phone application, all I/O operations are restricted to
isolated storage and do not have direct access to the underlying
operating system file system or to the isolated storage of other
applications.
So you can't access your Images folder in the manner you'd like.
Since you can't add images dynamically to your XAP anyway, the images available will be constant. It appears you will just have to add the URIs manually:
BitmapImage myImage = new BitmapImage(new Uri("Images/myImage.png", UriKind.Relative));
If you've got different images for different locales, you could include the image name/path in a resources file and then create them from there.
Alternatively if you have a set of default images and will then have some user-added ones, and you'd like to iterate over all of those, you could write your defaults from your Images folder into IsolatedStorage at first start-up. See here for details on using IsolatedStorage. You can iterate over directories and files within the apps IsolatedStorageFile (see the methods available).
Maybe you want to use
string path = Path.Combine(Environment.CurrentDirectory, "Images");
foreach (string file in Directory.GetFiles(path)
{
photos.Add(new Photo {FileName = file, PhotoSource = GetImageSource(Path.Combine(path, Path.GetFileNameWithoutExtension(file))});
}
which returns a List of the Contents of the Folder.
Path.Combine combines single strings to a full Path (So you don't need to worry about the Backslahes.
The Path Namespace is pretty underrated, i'd suggest you to take a close look to it since it will save you much time.
I am using XNA and I want to save files to Vista's "Saved Games" folder.
I can get similar special folders like My Documents with Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) but I cannot find an equivalent for the Saved Games folder. How do I get to this folder?
http://msdn.microsoft.com/en-us/library/bb200105.aspx#ID2EWD
Looks like you'll need to use Microsoft.Xna.Framework.Storage and the StorageLocation class to do what you need to.
Currently, the title location on a PC
is the folder where the executable
resides when it is run. Use the
TitleLocation property to access the
path.
User storage is in the My Documents
folder of the user who is currently
logged in, in the SavedGames folder. A
subfolder is created for each game
according to the titleName passed to
the OpenContainer method. When no
PlayerIndex is specified, content is
saved in the AllPlayers folder. When a
PlayerIndex is specified, the content
is saved in the Player1, Player2,
Player3, or Player4 folder, depending
on which PlayerIndex was passed to
BeginShowStorageDeviceSelector.
There is no special folder const for it so just use System Variables. According to this Wikipedia article Special Folders, the saved games folder is just:
Saved Games %USERPROFILE%\saved games Vista
So the code would be:
string sgPath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("USERPROFILE"), "saved games"));
...
EDIT: If, as per the comments, localization is an issue and as per your question you still want access to the Saved Games folder directly rather than using the API, then the following may be helpful.
Using RedGate reflector we can see that GetFolderPath is implemented as follows:
public static string GetFolderPath(SpecialFolder folder)
{
if (!Enum.IsDefined(typeof(SpecialFolder), folder))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, GetResourceString("Arg_EnumIllegalVal"), new object[] { (int) folder }));
}
StringBuilder lpszPath = new StringBuilder(260);
Win32Native.SHGetFolderPath(IntPtr.Zero, (int) folder, IntPtr.Zero, 0, lpszPath);
string path = lpszPath.ToString();
new FileIOPermission(FileIOPermissionAccess.PathDiscovery, path).Demand();
return path;
}
So maybe you think all i need is to create my own version of this method and pass it the folder id for Saved Games. That wont work. Those folder ids pre-Vista were actually CSIDLs. A list of them can be found here. Note the Note: however.
In releasing Vista, Microsoft replaced CLSIDLs with KNOWNFOLDERIDs. A list of KNOWNFOLDERIDs can be found here. And the Saved Games KNOWNFOLDERID is FOLDERID_SavedGames.
But you don't just pass the new const to the old, CLSIDL based, SHGetFolderPath Win32 function. As per this article, Known Folders, and as you might expect, there is a new function called SHGetKnownFolderPath to which you pass the new FOLDERID_SavedGames constant and that will return the path to the Saved Games folder in a localized form.
The easiest way I found to get the Saved Games path was to read the Registry value likes this:
var defaultPath = Path.Combine(Environment.GetEnvironmentVariable("USERPROFILE"), "Saved Games");
var regKey = "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders";
var regKeyValue = "{4C5C32FF-BB9D-43b0-B5B4-2D72E54EAAA4}";
var regValue = (string) Registry.GetValue(regKey, regKeyValue, defaultPath);
I changed the location of my Saved Games via the Shell multiple times and the value of this key changed each time. I use the USERPROFILE/Saved Games as a default because I think that will work for the default circumstance where someone has never changed the location.