![]() |
Languages »
C# »
General
License: The Code Project Open License (CPOL)
Extended Cursors for .NetBy MARROW16A design-time component to make use of animated/multi-coloured cursors |
C# (C#1.0, C#2.0, C#3.0)
|
||||||||||
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
ExtCursor is a design-time component that can be dropped onto a .Net form to make use of animated (.ani) and multi-coloured (.cur) cursors on that form.
The libary also supplies an ancillary component, ExtCursorsLink, that provides an extended property on all controls on parent the form - which facilitates the setting of an extended cursor at design-time. There is also an internal, singleton component that manages the sharing of cursor handles.
I'm not advocating the excessive use of animated and coloured cursors within applications - overuse can be just as detremental to UI consistency as too many colours or fonts etc.
I was recently working on a project where we wanted to use a couple of animated cursors to indicate to the user that some specific background task was taking place - similar to AppStarting (or background busy). We also needed to be able to load cursors from images and imagelists at runtime - the proposed application having a toolbox (similar to the VS IDE toolbox) where items in the toolbox could also be defined dynamically by the user. When loading cursors from images or imagelists, the code needed to be able to automatically add the 'crosshair' to the cursor image (so the user did not have to create an image for the toolbox item both with and without the crosshair).
Seemed like an incidental part of the design at first glance without considering the limitations of the .Net Cursor class:-
I scouted around MSDN and CodeProject, even trawled through the .Net source to find a quick and easy solution to these limitations. Most of these seemed to point to using the WinAPI LoadCursorFromFile() function, but I knew from previous experience that the LoadImage() function provided a slightly better alternative as it gave additional useful parameters - such as the desired height/width from cursor files containing multiple sizes.
Both functions were going to involve saving any internal cursor resources out to a temporary file, not something I was particularly keen on - but MS themselves actually do it in some circumstances within the .Net source.
I did explore utilising the HINSTANCE hinst parameter of the LoadImage() function to load the cursor data directly from an embedded resource, but when I started to explore the design ideas I decided against this because, as mentioned in the next section, I wanted to load the cursor data either from a .resx project resource or from a local resource stored within the form .resx. Another hinderance to using the HINSTANCE would have been that .Net doesn't provide a native resource template for .ani animated cursor files (resource type ID 21) - so getting these into application resources was going to mean messing around editing .rc (resource script) files, compiling them into a .res (resource) file and finally getting that resource file into the compiled .exe - way, way too much like hard work!
If you've done a search on animated cursors and .Net to end up here then you're probably aware of much of the above!
I decided that writing a component that could be easily used and re-used seemed the best, if far from economical, solution to the problems. Therefore, the design requirements were:-
You should now see the two ExtCursors components in the Toolbox, e.g.
[fig. 1] Toolbox example
To load a cursor (.ani or .cur) into a project resource:-
(This only needs to be done if you want to load cursors from project resources - the ExtCursor component has other options for loading cursors at design-time)
Open the form designer of the form you wish to use the cursor on, select the ExtCursor component from the Toolbox and drop it onto your form. The properties for the newly created ExtCursor will look llike:-
[fig. 2] ExtCursor properties
The usage of the ExtCursor component properties is as follows:-
Cursor - use this property to specify the local or project resource from which the cursor is to be loaded. Local resources are stored in the .resx of the form. Enter a filename into this property to specify a cursor file that is to be stored as a local resource. Press the elipses button of this property to bring up the Select Resource dialog, as shown below:-
[fig. 3] Select Resource dialogSelect the cursor from either a file (by checking the Local Resource radiobutton and pressing the Import... button under local resource) - the cursor being stored as a local resource. Alternatively, check the Project resource file radiobutton and select the project resource file from the combo and then the cursor in that resource.
Note: The Import button for the project resource option does not work and is permanently disabled - as I have not discovered how to get this to work - any suggestions welcome!CursorLocation - use this property to specify a file from which the cursor is to be loaded at runtime.
CursorLocationLocal - set this property totrueif the file location specified by the CursorLocation property will be local to the executable at runtime. In which case, the file path will be converted to a path relative to the folder containing the executable.SharedHandle - set this property to
trueif you want this cursor to share (re-use) the handle of another ExtCursor loaded from the same resource.SizeDefault & SizePreferred - these properties determine which actual cursor will be loaded from cursor files containing multiple size cursors. These properties are translated into the flags and parameters used by the LoadImage() function. Specifically, the SizePreferred property is used to set the
cxDesiredandcyDesiredparameters, and the SizeDefault is used to determine if theLR_DEFAULTSIZEflag is set on thefuLoadparameter.Size & HotSpot - these properties are informational only and are, therefore, read-only.
The hotspot can be set when loading cursors from images or imagelists using the constructors outlined below.
The ExtCursorsLink component provides an extended property on all controls on the form (and the form itself) that allows an ExtCursor component to be selected as the cursor for that control.
Drop the ExtCursorsLink component onto the form and then all controls and the form itself will have an additional property of Cursor on extCursorsLink, as shown in the example below:-
[fig. 4] ExtCursorsLink extended property example
Select the ExtCursor from the dropdown list on this property to set the cursor required on the control.
The ExtCursor class can also be instantiated in code (rather than as a drop-on component) using numerous overloaded constructors that allow the cursor to be loaded from file, stream, resource, image or imagelist. These overloaded constructors are briefly outlined below:-
public ExtCursor(
Stream pCursorStream
)
public ExtCursor(
Stream pCursorStream,
bool pDefaultSize,
Size pPreferredSize
)
public ExtCursor(
byte[] pCursorData
)
public ExtCursor(
byte[] pCursorData,
bool pDefaultSize,
Size pPreferredSize
)
pCursorStream or pCursorData parameter specifies the stream/byte data contianing the cursor. pDefaultSize and pPreferredSize parameters determine which actual cursor will be loaded from cursor streams/data containing multiple size cursors. These parameters are translated into the flags and parameters used by the LoadImage() function. Specifically, the pPreferredSize parameter is used to set the cxDesired and cyDesired parameters, and the pDefaultSize is used to determine if the LR_DEFAULTSIZE flag is set on the fuLoad parameter. public ExtCursor(
string pFilename
)
public ExtCursor(
string pFilename,
bool pShareable
)
public ExtCursor(
string pFilename,
bool pDefaultSize,
Size pPreferredSize
)
public ExtCursor(
string pFilename,
bool pDefaultSize,
Size pPreferredSize,
bool pShareable
)
pFilename parameter specifies the file from which the cursor is to be loaded (which should be a correctly encoded .cur or .ani file) pDefaultSize and pPreferredSize parameters determine which actual cursor will be loaded from cursor streams/data containing multiple size cursors. These parameters are translated into the flags and parameters used by the LoadImage() function. Specifically, the pPreferredSize parameter is used to set the cxDesired and cyDesired parameters, and the pDefaultSize is used to determine if the LR_DEFAULTSIZE flag is set on the fuLoad parameter. pShareable parameter determines whether the cursor handle should be shared. When this parameter is specified as true any ExtCursor objects that are also shared and load from the same file will use the same cursor handle. If this paramater is unspecified then true is the default. public ExtCursor(
Assembly pResourceAssembly,
string pResXName,
string pResourceName
)
public ExtCursor(
Assembly pResourceAssembly,
string pResXName,
string pResourceName,
bool pShareable
)
public ExtCursor(
Assembly pResourceAssembly,
string pResXName,
string pResourceName,
bool pDefaultSize,
Size pPreferredSize
)
public ExtCursor(
Assembly pResourceAssembly,
string pResXName,
string pResourceName,
bool pDefaultSize,
Size pPreferredSize,
bool pShareable
)
pResourceAssembly parameter is the assembly containing the project resource. pResXName parameter is the name of the project resource. For example, if the project is named 'Demo' and the Properties folder of the project contains Resources.resx then this parameter would be specified by the string "Demo.Properties.Resources". pDefaultSize and pPreferredSize parameters determine which actual cursor will be loaded from cursor streams/data containing multiple size cursors. These parameters are translated into the flags and parameters used by the LoadImage() function. Specifically, the pPreferredSize parameter is used to set the cxDesired and cyDesired parameters, and the pDefaultSize is used to determine if the LR_DEFAULTSIZE flag is set on the fuLoad parameter. pShareable parameter determines whether the cursor handle should be shared. When this parameter is specified as true any ExtCursor objects that are also shared and load from the same file will use the same cursor handle. If this paramater is unspecified then true is the default. public ExtCursor(
Bitmap pCursorImage,
Point pHotSpot
)
public ExtCursor(
Bitmap pCursorImage,
Bitmap pCursorMaskImage,
Point pHotSpot
)
public ExtCursor(
Bitmap pCursorImage,
Point pHotSpot,
bool pWithCrossHairs
)
public ExtCursor(
Bitmap pCursorImage,
Color pTransparentColor,
Point pHotSpot
)
public ExtCursor(
Bitmap pCursorImage,
Color pTransparentColor,
Point pHotSpot,
bool pWithCrossHairs
)
pCursorImage parameter specifies the bitmap from which the cursor is to be created. pHotSpot parameter specifies the point in the image to be used as the cursor hot spot. If the pHotSpot parameter is not specified then a default of 0,0 is used (unless the pWithCrossHairs parameter is specified as true - in which case the hot spot defaults to 5,5). pTransparentColor is the colour in the image to be treated as the transparent mask colour. If this parameter is unspecified (and the pCursorMaskImage parameter is also not passed) then the transparent colour is defaulted to the colour of the pixel at the bottom-left of the image. pWithCrossHairs parameter is specified with a value of true then cross-hairs are added to the created cursor (and the cursor size is increased accordingly). pCursorMaskImage parameter specifies a bitmap to be used as the transparent mask for the cursor. (For more information on using this parameter consult the documentation on the ICONINFO structure). public ExtCursor(
ImageList pImageList,
int pImageIndex,
Point pHotSpot
)
public ExtCursor(
ImageList pImageList,
int pImageIndex,
Point pHotSpot,
bool pWithCrossHairs
)
pImageList and pImageIndex parameters specify the imagelist and index of the image within that list from which the cursor is to be created. pHotSpot parameter specifies the point in the image to be used as the cursor hot spot. If the pHotSpot parameter is not specified then a default of 0,0 is used (unless the pWithCrossHairs parameter is specified as true - in which case the hot spot defaults to 5,5). pWithCrossHairs parameter is specified with a value of true then cross-hairs are added to the created cursor (and the cursor size is increased accordingly). One of the trickiest bits of coding was to populate the information in the Select Resource dialog (see Fig. 3 above) - in particular obtaining the list of resources within the 'host' project to populate the combobox with and the list of appropriate cursor (.cur and .ani files) within each project resource. All of the code to do this in the file ExtCursorResourceEditorDialog.cs - and uses, as the starting point, the IServiceProvider and ITypeDescriptorContext objects that are passed to the UITypeEditor.EditValue override method (in ExtCursorEditor.cs).
When creating cursors from images (using the CreateIconIndirect() function) a mask image is required in the ICONINFO structure. Writing a graphics routine to generate this mask is superfluous when the windows ImageList has just such a routine that can be borrowed. Unfortunately the .Net ImageList class does not expose a method that makes use of the ImageList_Draw() function passing a parameter to denote that the mask is required (ILD_MASK flag set in the fStyle parameter). The code to perform this can be found in ExtCursor.cs (in the private method CreateImageAndMask).
| You must Sign In to use this message board. | |||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads.
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 2 Feb 2009 Editor: |
Copyright 2009 by MARROW16 Everything else Copyright © CodeProject, 1999-2010 Web17 | Advertise on the Code Project |