Help! Load Cursor Resource from Assembly Not File?

  • Thread starter Thread starter Schorschi
  • Start date Start date
S

Schorschi

I am trying to mimic the following (which works) but Use the stock
GetManifestResourceStream route.

For example

Public Declare Unicode Function LoadCursorFromFile Lib "USER32.DLL"
Alias "LoadCursorFromFileW" (ByVal thePath As String) As IntPtr

Dim theCursor As Cursor

theCursor = New Cursor(LoadCursorFromFile(thePath))

Me.Cursor = theCursor

This works!

However, the following does not...

Dim theType As Type
Dim theStream As IO.Stream
Dim thePointer As IntPtr
Dim theBytes() As Byte
Dim theHandle As GCHandle

'

theType = GetCurrentMethod. _
ReflectedType

theStream =
[Assembly].GetAssembly(theType).GetManifestResourceStream _
(theType.Namespace & "." & thePath)


ReDim theBytes(CInt(theStream.Length + 4 - 1))

theStream.Read(theBytes, 0, theBytes.Length)

theHandle = GCHandle.Alloc(theBytes,
GCHandleType.Pinned)
thePointer = theHandle.AddrOfPinnedObject

theCursor = New Cursor(thePointer)

Me.Cursor = theCursor

I get no errors, in fact, theStream is valid, ie. thePath is the path
to my cursor resource. 'theBytes' array has what I believe is the
binary of the stream. And the theCursor.Handle = thePointer (ie. the
..NET Cursor Class initializes pointing to the IntPtr.

Help!
 
Schorschi said:
I am trying to mimic the following (which works) but Use the stock
GetManifestResourceStream route.

For example

Public Declare Unicode Function LoadCursorFromFile Lib "USER32.DLL"
Alias "LoadCursorFromFileW" (ByVal thePath As String) As IntPtr

Dim theCursor As Cursor

theCursor = New Cursor(LoadCursorFromFile(thePath))

Me.Cursor = theCursor

This works!

However, the following does not...

Dim theType As Type
Dim theStream As IO.Stream
Dim thePointer As IntPtr
Dim theBytes() As Byte
Dim theHandle As GCHandle

'

theType = GetCurrentMethod. _
ReflectedType

theStream =
[Assembly].GetAssembly(theType).GetManifestResourceStream _
(theType.Namespace & "." & thePath)


ReDim theBytes(CInt(theStream.Length + 4 - 1))

theStream.Read(theBytes, 0, theBytes.Length)

theHandle = GCHandle.Alloc(theBytes,
GCHandleType.Pinned)
thePointer = theHandle.AddrOfPinnedObject

theCursor = New Cursor(thePointer)

Me.Cursor = theCursor

I get no errors, in fact, theStream is valid, ie. thePath is the path
to my cursor resource. 'theBytes' array has what I believe is the
binary of the stream. And the theCursor.Handle = thePointer (ie. the
.NET Cursor Class initializes pointing to the IntPtr.

Help!
How are you storing the cursor? If you've included it in your application
with a Build Action of Embedded Resource then you should be able to pass the
results of Assembly.GetManifestResourceStream() to the constructor of Cursor
which accepts a System.IO.Stream.

Regards,

Nick Hall
 
Nope, that generates and error. The data in the stream is NOT .CUR
formated sequence, so the .NET Cursor Class aborts. .NET Cursor Class
will NOT accept .ani binary sequence stream. Hence, I am trying to
get the stream referenced as IntPtr, which means that .NET Cursor
Class .Handle reference can be assigned to this IntPtr that really
points to the Stream... Or a unmanaged memory location that is a
duplicate of the stream. That is why I am trying to Pin the (stream)
data.

What bugs me, is the LoadCursorFromFile API call just loads the .ANI
data raw, and the .NET Cursor Class accepts it. But when I use the
stream, the .NET Cursor Class does its own validation to BLOCK any
thing that is not .CUR compliant. Or so it seems.
 
Schorschi said:
Nope, that generates and error. The data in the stream is NOT .CUR
formated sequence, so the .NET Cursor Class aborts. .NET Cursor Class
will NOT accept .ani binary sequence stream. Hence, I am trying to
get the stream referenced as IntPtr, which means that .NET Cursor
Class .Handle reference can be assigned to this IntPtr that really
points to the Stream... Or a unmanaged memory location that is a
duplicate of the stream. That is why I am trying to Pin the (stream)
data.

What bugs me, is the LoadCursorFromFile API call just loads the .ANI
data raw, and the .NET Cursor Class accepts it. But when I use the
stream, the .NET Cursor Class does its own validation to BLOCK any
thing that is not .CUR compliant. Or so it seems.

LoadCursorFromFile is returning a HCURSOR (i.e. an opaque pointer to a
private data structure that Windows holds). It's not just an arbitrary
buffer. Reading between the lines, the Cusor constructor that takes an
IntPtr is actually expecting an HCURSOR as well (since the results of
calling LoadCursorFromFile are satisfactory to it).

Having just looked at the help for the Cursor constructor, it appears that
the framework 1.1 Cursor class does not support animated cursors. You might
want to check out the following link for a possible solution: -

http://www.vbaccelerator.com/home/NET/Code/Libraries/Graphics/Animated_Cursors_in__NET/article.asp

Cheers,

Nick Hall
 
Nick,

Thanks, I found this code as well... And it is cool, just not what I
was thinking of doing. But it did give me an a reason to do some async
C#, EVEN though I do VB .NET most of the time... Our lab is straight C
or VB .NET, go figure. I have old timers and green horns, not much in
the middle. I code for fun, and help the guys in the lab... When I am
not doing server/network enterprise integration (my real job).

My final solution is unique but not wonderful... I embed the ANI file
in a project, then open a stream to it, write it out to a temporary
location, use WIN API LoadCursorFromFile to load this temporary copy,
then delete the now useless temporary file. THIS is a bit crazy, but
since we hold our animated icons for long periods of time (we do not
change images much in the application, this trick is ok for now.

I even went so far as to write a simple RIFF (RIFX) parser, to get the
number of ICON frames, to improve on the example code referenced
above... Since I thought drawing each frame to count icon frames was a
bit much, but this was more to learn the ANI file data structure than
an real expectation of use.
 
Back
Top