Cursor Hot Spots lost when reading from managed resources?

P

Peter Bromley

Hi,

Cursor hot-spots don't seem to to be stored or loaded properly for my
custom cursors.

If I create a Cursor (System::Windows:Forms::Cursor) from a file, the
hot-spot is correct (near the top-left corner of the cursor image).

But if I load a cursor into a resX file using a ResXResourceWriter, and
thence into a managed resources file, the cursor hot-spot is not correct
(in the center of the cursor image).

Am I doing something wrong? Or is there a bug?

Some C++ code:

ResXResourceWriter* resX = new ResXResourceWriter(S"out.resX");
Cursor cursor = new Cursor(S"MyCursor.cur");
resX->AddResource(S"MyCursor", cursor);
resX->Close();

and loading:

ResourceManager* rm = new ResourceManager(S"MyCursors",
Assembly::GetExecutingAssembly());
Cursor cursor = __try_cast<Cursor*>(resources->GetObject(S"MyCursor"));

Thanks,

--
If you wish to reply to me directly, my addres is spam proofed as:

pbromley at adi dot co dot nz

Or if you prefer - (e-mail address removed) :)
 
Y

Ying-Shen Yu[MSFT]

Hi Peter,

Thanks for your feedback!

This is a known issue for serializing Cursor object in current .NET
framework.

To workaround this issue, we need save a copy of the .Cur file. serialize
the content of this file instead . We may write a CursorWrapper class to
help us do this.

I found a sample code for you, you need change it to fit your needs.
You need load .cur file into CursorWrapper class instead then access the
Cursor property instead.

If the workaround does not solve your problem, you may contact Phone
service for further help.

Thanks!

<code>
using System;
using System.ComponentModel;
using System.IO;
using System.Windows.Forms;
using System.Globalization;
using System.Runtime.Serialization;

namespace MyCursor
{
[Serializable]
[TypeConverterAttribute(typeof(CursorWrapperConverter))]
public class CursorWrapper : ISerializable
{
Cursor _cursor;
byte[] _originalFile;

internal CursorWrapper(SerializationInfo info, StreamingContext context)
{
SerializationInfoEnumerator sie = info.GetEnumerator();
if (sie == null)
{
return;
}
for (; sie.MoveNext();)
{
if (String.Compare(sie.Name, "CursorData", true,
CultureInfo.InvariantCulture) == 0)
{
byte[] dat = (byte[])sie.Value;
try
{
if (dat != null)
{
_originalFile = dat;
CursorConverter cc = new CursorConverter();
_cursor = (Cursor)cc.ConvertFrom(OriginalFile);
}
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
}
}

public CursorWrapper(Stream stream)
{
_originalFile = new byte[stream.Length];
stream.Read(_originalFile, 0, _originalFile.Length);
CursorConverter cc = new CursorConverter();
_cursor = (Cursor) cc.ConvertFrom(_originalFile);
}

public Cursor Cursor
{
get { return _cursor; }
}

internal byte[] OriginalFile
{
get { return _originalFile; }
}

void ISerializable.GetObjectData(SerializationInfo si, StreamingContext
context)
{
si.AddValue("CursorData", OriginalFile, typeof(byte[]));
}
}

public class CursorWrapperConverter : TypeConverter {
public override bool CanConvertFrom(ITypeDescriptorContext context, Type
sourceType)
{
if (sourceType == typeof(byte[]))
{
return true;
} return base.CanConvertFrom(context, sourceType);
}

public override bool CanConvertTo(ITypeDescriptorContext context, Type
destinationType)
{
if (destinationType == typeof(byte[]))
{
return true;
} return base.CanConvertTo(context, destinationType);
}

public override object ConvertFrom(ITypeDescriptorContext context,
CultureInfo culture, object value)
{
if (value is byte[])
{
MemoryStream ms = new MemoryStream((byte[])value);
return new Cursor(ms);
} return base.ConvertFrom(context, culture, value);
}

public override object ConvertTo(ITypeDescriptorContext context,
CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(byte[]))
{
if (value != null)
{
return ((CursorWrapper)value).OriginalFile;
}
else
return new byte[0];
}

return base.ConvertTo(context, culture, value, destinationType);
}
}
}

</code>


Best regards,

Ying-Shen Yu [MSFT]
Microsoft Community Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
This mail should not be replied directly, please remove the word "online"
before sending mail.
 
P

Peter Bromley

Ying-Shen Yu said:
Hi Peter,

Thanks for your feedback!

This is a known issue for serializing Cursor object in current .NET
framework.

To workaround this issue, we need save a copy of the .Cur file. serialize
the content of this file instead . We may write a CursorWrapper class to
help us do this.

I found a sample code for you, you need change it to fit your needs.
You need load .cur file into CursorWrapper class instead then access the
Cursor property instead.

If the workaround does not solve your problem, you may contact Phone
service for further help.

Aha!

I notice there is no Knowledge Base article on MS web site :-(

Thanks for the code sample. I will work with that.

Will the problem be fixed in Whitbey?

Cheers,


--
If you wish to reply to me directly, my addres is spam proofed as:

pbromley at adi dot co dot nz

Or if you prefer - (e-mail address removed) :)
 
Y

Ying-Shen Yu[MSFT]

Hi Peter,

Currently, the product team is investigating this issue and planning to fix
it in Whidbey.

Best regards,

Ying-Shen Yu [MSFT]
Microsoft Community Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
This mail should not be replied directly, please remove the word "online"
before sending mail.
 
P

Peter Bromley

Hi,

I have tried implementing the code snippet you posted and it appears to
work.

But I have a further problem and MSDN documentation is not really helping.
I have serialized a CursorWrapper to a resX file using a
ResXResourceWriter but when I try to compile the resX file using ResGen
I get this error -

error: Invalid ResX input.
error: Specific exception: TypeLoadException Message: Invalid ResX
input. ---> TypeLoadException: Could not load type
MyNamespace.CursorWrapper from assembly System.Windows.Forms,
Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.

There is no real documentation on how ResGen reads resX file but it
appears that it assumes that all types encoded in the resX file are
expressed in the System.Windows.Forms dll. How do I inform ResGen that
the type is expressed in my DLL instead?

Any help would be appreciated.
This is a known issue for serializing Cursor object in current .NET
framework.

To workaround this issue, we need save a copy of the .Cur file. serialize
the content of this file instead . We may write a CursorWrapper class to
help us do this.

I found a sample code for you, you need change it to fit your needs.
You need load .cur file into CursorWrapper class instead then access the
Cursor property instead.

--
If you wish to reply to me directly, my addres is spam proofed as:

pbromley at adi dot co dot nz

Or if you prefer - (e-mail address removed) :)
 
Y

Ying-Shen Yu[MSFT]

Hi,

The TypeLoadException means resgen could not load the correct type.
several issues might cause this problem:
1. what's the value in the data element in your resX file, especially the
type attribute. resgen will try to get type using the this full qualified
type name. Here is a sample in my resx file:
<data name="MyCursor" type="MyCursor.CursorWrapper, resx, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=45bfccc78a7424dc"
mimetype="application/x-microsoft.net.object.bytearray.base64">

2. normally resgen.exe is not under the same directory with your assembly,
so it could not find your assembly automatically, for more information
please refer to the chapter "How the Runtime Locates Assemblies" (mainly
steps 4)
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
l/cpconhowruntimelocatesassemblies.asp

so to workaround this issue, you may copy the resgen.exe to the same
directory with your assembly or register your assembly into GAC.

Does it resolve your issue?

If you meet any problem when using my workarounds, please feel free to
reply this thread.

Have a nice day!

Best regards,

Ying-Shen Yu [MSFT]
Microsoft Community Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
This mail should not be replied directly, please remove the word "online"
before sending mail.
 
Top