Portability worries because of custom cursor path in C# - c#

I am using a custom cursor named hand2.cur in my C#-WPF application. I have added the cursor to a folder named Images which has all the images that I use in my application. However I've realized that I cannot add relative path to use my custom cursor as:
Cursor newCur = new Cursor("Images\\hand2.cur");
window.Cursor = newCur;
So I used this:
string absolute = System.IO.Path.GetFullPath("hand2.cur");
Cursor newCur = new Cursor(absolute);
window.Cursor = newCur;
This tries to find the hand2.cur file in the \bin\Release folder. So I added the file there and I got it working.
But the problem is, if I Publish this application and use it on a different computer, it does not work. Now the problem is with the cursor file path, because if I deploy it after commenting those 3 lines, it works correctly. So what do I do to rectify this problem?
I am using other images from the Image folder in my XAML code and they seem to port fine. But then again my knowledge of WPF is limited so if anyone has any ideas, that would help.
EDIT: I have added my Images folder to the project. I have also set the Build Action of the cursor file hand2.cur to Embedded Resource. However when I use the following two lines, I get an XAMLParseException.
System.Windows.Resources.StreamResourceInfo info = Application.GetResourceStream(new Uri("pack://application:,,,/Slideshow;component/Images/hand2.cur"));
window.Cursor = new System.Windows.Input.Cursor(info.Stream);
The Inner Exception field when I view the details of the error reads: {"Cannot locate resource 'images/hand2.cur'."}

You could make the cursor a resource in your app/assembly and then use GetResourceStream with the pack Uri to the resources location. Pass the Stream of the StreamResourceInfo to the ctor of the Cursor. e.g.
var info = Application.GetResourceStream(new Uri("pack://application:,,,/Images/hand2.cur"));
var cursor = new Cursor(info.Stream);

I've got this working after I added the cursor file hand2.cur to my Resource1.resx resource file. Then I used the following statement in my code:
window.Cursor = new Cursor(new System.IO.MemoryStream(MyNameSpace.Resource1.hand2));

Related

Difference between #"pack://application:,,,[...] and IO.Directory.GetCurrentDirectory()?

I've noticed that when I add a line of <Window.Background></Window.Background> in the XAML file or in the C# code this.Background = new ImageBrush(new BitmapImage(new uri([...])); if I put in the "Uri" this: new Uri(#"pack://application:,,,/Myapp;component/image.jpg") I get an error when I try to compile it which says: "Could not locate resource "image.jpg" "
But if I change this to new Uri(System.IO.Directory.GetCurrentDirectory()+"\\image.jpg"); it never gives me an error. Why???? What is the difference between both methods? I am very comfortable with Directory but why the compiler doesn't show an error "Locating" the resource with IO.Directory? What's the difference?
The questions may sound too noob, but I don't understand why it gives an error in #"pack://application[...] and not with GetCurrentDirectory()
A pack:// Uri, will search embedded resources for the image. The resources are inside the DLL/EXE, rather than deployed to the same folder. To use an image as a WPF Resource you need to set the Build Action on the image to Resource.
Using the Directory approach simply searches the physical file system for the image.
More info here on WPF Pack Uri's.

C# - Loading image from file resource in different assembly

C# - Loading image from file resource in different assembly
I have a PNG image file which is stored in a project called SomeProject and displayed various times using XAML in that same project. In a different assembly, I now wish to access that same image. Previously I was simply specifying a relative path to the actual file which worked fine. However, when I build a release installer, the image files are packed into the SomeProject.DLL.
Is there any easy way I can access the PNG file from another assembly without simply resorting to copying the file locally to the second project? I though it might be possible using 'pack://' but I'm not having much luck.
// SomeOtherProject.SomeClass.cs ...
Image logo = new Image();
BitmapImage logoSource = new BitmapImage();
eChamSource.BeginInit();
// Following line works fine is Visual Studio, but obviously not after installation
// logoSource.UriSource = new Uri(#"..\SomeProject\Resources\Images\logo.png", UriKind.Relative);
logoSource.UriSource = new Uri("pack://application:,,,/SomeProject;component/Resources/Images/logo.png");
logoSource.EndInit();
logo.Width = 100; logo.Height = 100;
logo.Source = logoSource;
Any advice would be good.
If the images you wish to use as Content is in another assembly, you must copy them to the main projects directory.
You can use a Build event to do this:
Right click project that contains images -> Properties -> Buil Events -> edit post build to copy images to main project directory.
Then you have to use it as
pack://application:,,,/ContentFile.xaml
(Or)
If you need it in subfolder
pack://application:,,,/Subfolder/ContentFile.xaml
Have a look at this hfor more information http://msdn.microsoft.com/en-us/library/aa970069.aspx
Try to load your other assembly as followed:
Application.LoadComponent(new Uri(#"AnotherAssembly;;;component\AnotherResourceFilePath/logo.png", UriKind.Relative)));
LoadComponent function returns an object. It is up to you to cast it to the appropriate type.

PNG and jpg images not appearing in C# application

I have a problem with displaying certain images in my application using C#. I am using the Image class to specify the location and the BitmapImage to specify the source. The UriSource is relative and I just specify the name. It worked for some images, but for others, the image simply does not appear. My image instance is 35x35 big and another is 100x100 big (pixels).
Anyone knows why this might be occurring and how to fix it?
Thanks.
Here's the code I used:
Image removeImage = new Image();
removeImage.HorizontalAlignment = HorizontalAlignment.Left;
removeImage.VerticalAlignment = VerticalAlignment.Top;
removeImage.Margin = new Thickness(490, 10, 0, 0);
removeImage.Width = 35;
removeImage.Height = 35;
BitmapImage source = new BitmapImage();
source.BeginInit();
source.UriSource = new Uri("delete.png", UriKind.RelativeOrAbsolute);
source.EndInit();
removeImage.Source = source;
removeImage.Stretch = Stretch.None;
removeImage.Visibility = Visibility.Visible;
removeImage.MouseDown += new MouseButtonEventHandler(removeImage_MouseDown);
Not sure about the location of image files. If images are in your current project folder then you have to set Copy To Output Directory=Copy Always property of image file from Properties Windows.
The best way that I know of to diagnose a problem like that (assuming a quick peer review of the code gets you nowhere), is to use ProcessMonitor: http://technet.microsoft.com/en-us/sysinternals/bb896645
You can use this tool to monitor all of the file activity on your machine (make sure to use the include/exclude filters to limit the noise).
It's very likely that the reason that the images are not showing up is because your application is looking for them in the wrong place (either they didn't get copied, or the relative path is off).
ProcessMonitor will log every attempt that Windows makes to access your .jpg (whether it fails or succeeds). If you search for your file name in the log, you should find it, probably along with an error message, and the full path that Windows was using to open the file.
The most common results I see are
Path that was actually being used was different from the path you needed.
The path was correct, but your files weren't there (build/copy/install problem)
The path was correct, but your web app did not have permissions to read the file.
In all those cases, ProcessMonitor will show you what happened.

Dynamically loading resource dictionary files to a wpf application gives an error

I am trying to add a xaml resource file dynamically using the statement,
Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("resources/leaf_styles.xaml", UriKind.Relative) });
This is throwing an exception, Cannot locate resource 'resources/leaf_styles.xaml'.
I added the leaf_styles.xaml file to the project under resource folder and the BuildAction is set to "Content", CopyAlways is set to True. Still I get this error. Could some one help me out pointing whats wrong??
Additional information -
I don't want to embed the xaml file as a resource
The current project is a .net 3.5 class library project
The above mergedictionary statement is written in a class belonging to the same project
I also added the [assembly: AssemblyAssociatedContentFile("resources/leaf_styles.xaml")] manually once I figured that this is not working (for testing)
Update
If I give it as an absolute location, it is working properly.
Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri(#"D:\foo\trunk\bin\resources\leaf_styles.xaml", UriKind.Absolute) });
At last, it worked. Here is what I did,
Went thru' http://msdn.microsoft.com/en-us/library/aa970069.aspx.
Changed the Uri pattern to
var foo = new Uri("pack://siteoforigin:,,,/resources/leaf_styles.xaml", UriKind.RelativeOrAbsolute);
Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = foo });
To load a content file, you can call the GetContentStream method of the Application class, passing a pack URI that identifies the desired content file.
Checkout
http://msdn.microsoft.com/en-us/library/aa970494.aspx#Content_Files
EDIT
I did it successfully like this
Uri uri = new Uri("Resources/MyDict.xaml", UriKind.Relative);
StreamResourceInfo info = Application.GetContentStream(uri);
System.Windows.Markup.XamlReader reader = new System.Windows.Markup.XamlReader();
ResourceDictionary myResourceDictionary =
(ResourceDictionary)reader.LoadAsync(info.Stream);
Application.Current.Resources.MergedDictionaries.Add(myResourceDictionary);
I encountered same "missing resource problem" and scratched my head for hours. Then I realized that my assembly name contains dots (.) and changed the resource assembly name, tested again and it worked. It was a 16x16 png image file which ı wanted to load. But I see that dotted assembly names causes error for soma cases and does not cause error for other cases.
1) If you are loading a style from resource, it works
2) If you are loading an image, it does not work. The resource can not be found.
I used the same code for both cases but results are different. I don't know if it is a wpf bug.

Using Custom Cursor WinForms

Is there a way to use a custom cursor in winforms?
There seems to be no option. But when I try to manually add a cursor as a resource, then call it from code, it says that it cannot convert from type byte[] to Cursor.
Adding custom icon to cursor in C# :
Add Icon file to Project resources (ex : Processing.ico)
And in properties window of image switch "Build Action" to "Embedded"
Cursor cur = new Cursor(Properties.Resources.**Imagename**.Handle);
this.Cursor = cur;
Ex:
Cursor cur = new Cursor(Properties.Resources.Processing.Handle);
this.Cursor = cur;
From the MSDN documentation on the Cursor class (with minor corrections):
// The following generates a cursor from an embedded resource.
// To add a custom cursor, create or use an existing 16x16 bitmap
// 1. Add a new cursor file to your project:
// File->Add New Item->Local Project Items->Cursor File
// 2. Select 16x16 image type:
// Image->Current Icon Image Types->16x16
// --- To make the custom cursor an embedded resource ---
// In Visual Studio:
// 1. Select the cursor file in the Solution Explorer
// 2. Choose View->Properties.
// 3. In the properties window switch "Build Action" to "Embedded"
// On the command line:
// Add the following flag:
// /res:CursorFileName.Cur,Namespace.CursorFileName.Cur
//
// Where "Namespace" is the namespace in which you want to use
// the cursor and "CursorFileName.Cur" is the cursor filename.
// The following line uses the namespace from the passed-in type
// and looks for CustomCursor.MyCursor.Cur in the assemblies manifest.
// NOTE: The cursor name is case sensitive.
this.Cursor = new Cursor(GetType(), "MyCursor.Cur");
I've used the LoadCursorFromFile() method from User32.dll. There are plenty of samples for this on the web.
OR
The ctor for the Cursor type also has a IO.Stream overload. Load your byte[] into a MemoryStream and feed that to the new Cursor.
After adding the file to the resources, in the properties window of the image: switch Build Action to Embedded Resource and write in your code:
"name of control".Cursor = new System.Windows.Forms.Cursor(Properties.Resources."name of image".Handle);
Convert your cursor from any format to ico using convertico.com(It is the best way of doing this), copy your cursor to your project's debug folder using file explorer and write this code(C#):
this.Cursor = new Cursor("default.ico");
I had the same problem for a while. So, as far as I understood, these are 2 ways to solving that issue:
Putting cursor .ico file into the Resources
Getting cursor from .ico file without putting it the resources
First case:
After putting to the resources you can just add .Handle after the name of resource while getting it. For instance:
this.Cursor = new Cursor(Properties.Resources.YourResource.Handle);
Second case:
This one looks a bit easier, but before that you should add your .ico file to project and in properties of that file you should set Always copy for file to be copied automatically to the execution folder. After that you can easyly use this:
this.Cursor = new Cursor("YourIcon.ico");
To my mind, using the resources for permanent files like cursor icons is the best practice, so the used the first one.

Categories

Resources