Click here to Skip to main content
15,893,266 members
Articles / Desktop Programming / Windows Forms
Article

TdhCursorFactory - A Class to Provide Animated and Color Cursors to DotNET Applications

Rate me:
Please Sign up or sign in to vote.
4.65/5 (16 votes)
1 Nov 2007CPOL9 min read 58K   649   38   23
This article describes a class to manage animated and color cursors and make them available for use in .NET applications. The cursors may derive from embedded resources, from standard cursors, or from files read from disk.
Screenshot - TdhCursorFactory.gif

Introduction

The .NET System.Windows.Forms.Cursor class doesn't natively support animated or color cursors. (And, if the constructor doesn't throw an exception when passed a color cursor, the colors vanish). But, one can use the LoadCursorFromFileW function of "user32.dll" to get around this constraint.

The 'TdhCursorFactory' Class

The TdhCursorFactory class is built on a basis primarily of code published in this MSDN article: Using Colored and Animated Cursors; and secondarily Bingzhe Quan's Code Project article: A scrollable, zoomable, and scalable picture box. But, then it takes off into parts unknown.

The class is static; its primary purpose is to create .NET usable color and animated cursors. As an added bonus, it can maintain an array of Cursors for easy access by the program making use of the library. The Cursors stored in this array may be used to "override" the standard Cursors of the System.Windows.Forms.Cursors class.

A Note On The LoadCursorFromFileW Function

The LoadCursorFromFileW function of "user32.dll" requires its argument to be the name of an actual file on disk (I was unable to find if there is a similar function which can take a memory stream). Thus, when the methods of TdhCursorFactory must make use of the LoadCursorFromFileW function as part of the process of extracting a Cursor object from the embedded resources (i.e. for animated cursors or color non-animated cursors), the resource is first extracted into a memory stream, which is written to a temporary file. This temporary file is then passed as the argument to the LoadCursorFromFileW function (and deleted afterward).

On the other hand, a black-and-white non-animated cursor may be passed as a memory stream directly to the [new System.Windows.Forms.Cursor(stream)] constructor. By default, the TdhCursorFactory class attempts this with cursors having the ".CUR" extension.

So, effectively, the only real advantage to making animated cursors or color non-animated cursors embedded resources of your project is that since they are "inside" the assembly, they won't get lost.

Using The Class

To use TdhCursorFactory as is, add a reference in your project to the class library 'TDHCursorFactory.dll.' The namespace used in this library is:

C#
using TDHControls.TDHCursorFactory;
//
{
    // Sample usage:
    TdhCursorFactory.SetCursor(TdhCursorFactory.Cursors._Busy, 
        @"C:\SomePath\SomeCursor.ani");
    TdhCursorFactory.SetCursor(TdhCursorFactory.Cursors.WaitCursor, true,
        "Cursors.Cow_chewing.ani", true);
    //  
    // The following statement will return the Cursor loaded from
    // "C:\SomePath\SomeCursor.ani"  
    this.Cursor = TdhCursorFactory.GetCursor(TdhCursorFactory.Cursors._Busy);
    // 
    // At the moment, the following statement will return the 
    // "Cursors.Cow_chewing.ani" animated cursor 

    // (from the library's embedded resources)
    this.Cursor = TdhCursorFactory.GetCursor(
        TdhCursorFactory.Cursors.WaitCursor);
    //  
    TdhCursorFactory.UnsetCursor(TdhCursorFactory.Cursors.WaitCursor);
    // The following statement will now return the standard  
    // System.Windows.Forms.Cursors.WaitCursor Cursor object 
    this.Cursor = TdhCursorFactory.GetCursor(
        TdhCursorFactory.Cursors.WaitCursor);
    //   
    // There is no "EarlyBird.ani" in the Demo project's embedded resources  
    // ("Demo_Cursors" is the name of a folder under the Demo project)  
    // Thus, the following statement will have no effect upon the Cursor  
    // to which the enum value TdhCursorFactory.Cursors._Busy refers 
    TdhCursorFactory.SetCursor(TdhCursorFactory.Cursors._Busy, true,
        "Demo_Cursors.EarlyBird.ani", true);
    //  
    // There is a "Drum.ani" in the Demo project's embedded resources.  
    // However, this statement will not find it (the correct full-name is
    // "Demo_Cursors.Drum.ani")  
    TdhCursorFactory.SetCursor(TdhCursorFactory.Cursors._Busy, true,
        "Drum.ani", true);
    // The following statement will find the "Cursors.Drum.ani"
    // embedded resource  
    // in the Demo project's resources manifest.  
    TdhCursorFactory.SetCursor(TdhCursorFactory.Cursors._Busy, true,
        "Drum.ani", false);
    //   
    // The .FromFile() method always makes use of the LoadCursorFromFileW 

    // function of "user32.dll"  
    this.Cursor = TdhCursorFactory.FromFile(@"C:\SomePath\SomeCursor.cur",
        false);
    //   
    // The .FromResource() method makes use of   
    // * either the LoadCursorFromFileW function of "user32.dll"   
    // * or the the [new System.Windows.Forms.Cursor(stream)] constructor.   
    // If the extension is ".ANI," or if the first argument is 'true,'   
    // the LoadCursorFromFileW function will be used.   
    // Otherwise, an attempt is first made to use  
    // the [new System.Windows.Forms.Cursor(stream)] constructor.   
    // If that attempt fails, the LoadCursorFromFileW function is used.   
    this.Cursor = TdhCursorFactory.FromResource(false, 
        "Demo_Cursors.SomeCursor.cur", true, false);
}

The TdhCursorFactory class was written (and compiled) using VS2002 (.NET 1.0) with the intention that the source code be readily available to other developers regardless of the .NET version they are using.

The members of TdhCursorFactory's interface are:

  • Cursors — The items in the array of Cursors managed by the class are accessed via the TdhCursorFactory.Cursors enum (see below for a list of members).

  • public static System.Windows.Forms.Cursor GetCursor(TdhCursorFactory.Cursors whichCursor)
    This method returns a System.Windows.Forms.Cursor object from the array of cursors managed by the class, as named by the 'whichCursor' value. If that particular cursor has not been set, the method returns the standard System.Windows.Forms.Cursors.Default object.

  • public static void InitCursor_X(TdhCursorFactory.Cursors whichCursor)
    This method initializes the "sub-array" of Cursors referenced by the 'whichCursor' enum value (at this time, only the TdhCursorFactory.Cursors._X_Random_Busy enum member is so defined) to a set of pre-defined Cursor objects obtained from the class's resources manifest. The method is not executed automatically by the class's constructor, but rather if it is desired that these cursors be loaded, the method must be explicitly called by the main program.

  • public static void SetCursor(TdhCursorFactory.Cursors whichCursor, bool forceAsColor, string cursorName, bool caseSensitive)
    This method sets the managed Cursor named by 'whichCursor' to a System.Windows.Forms.Cursor object obtained from the embedded Resources of either: 1) the calling assembly, or 2) the TdhCursorFactory class' assembly. If the 'cursorName' value cannot be found in either assembly (or if it is not a valid Cursor), the method will leave the managed Cursor as is. The 'caseSensitive' value determines whether the 'cursorName' value must be given exactly. When this value is false, the class will examine all the object names contained in the assembly's resources manifest. The value of 'forceAsColor' allows the developer using the class to force ".CUR" files to be loaded via the LoadCursorFromFileW function of "user32.dll." (Cursors with the ".ANI" extension are always loaded via this function).

  • public static void SetCursor(TdhCursorFactory.Cursors whichCursor, string fileName)
    This method sets the managed Cursor named by 'whichCursor' to the System.Windows.Forms.Cursor object read from the file with the path given in 'fileName.' If the given path does not resolve to a valid Cursor, the method will leave the managed Cursor as is.

  • public static void SetCursor(TdhCursorFactory.Cursors whichCursor, System.Windows.Forms.Cursor theCursor)
    This method sets the managed Cursor named by 'whichCursor' to the System.Windows.Forms.Cursor object passed as 'theCursor.'

  • public static void UnsetCursor(TdhCursorFactory.Cursors whichCursor)
    This method releases the managed Cursor named by 'whichCursor.'

  • public static System.Windows.Forms.Cursor FromFile(string fileName, bool allowNull)
    This method returns a System.Windows.Forms.Cursor object read from the file with the path given in 'fileName.' If the given path does not resolve to a valid Cursor, the method will return either a null object or the System.Windows.Forms.Cursors.Default object, depending on the value of 'allowNull.'

  • public static System.Windows.Forms.Cursor FromResource(bool forceAsColor, string cursorName, bool caseSensitive, bool allowNull)
    This method returns a System.Windows.Forms.Cursor object obtained from the embedded Resources of either: 1) the calling assembly, or 2) the TdhCursorFactory class' assembly. If the 'cursorName' value cannot be found in either assembly (or if it is not a valid Cursor), the method will return either a null object or the System.Windows.Forms.Cursors.Default object, depending on the value of 'allowNull.' The 'caseSensitive' value determines whether the 'cursorName' value must be given exactly. When this value is false, the class will examine all the object names contained in the assembly's resources manifest. The value of 'forceAsColor' allows the developer using the class to force ".CUR" files to be loaded via the LoadCursorFromFileW function of "user32.dll." (Cursors with the ".ANI" extension are always loaded via this function).

  • public static System.Collections.ArrayList ResourcesManifest(bool forCallingAssembly)
    This method returns an ArrayList (of string objects) containing the fully qualified names of the ".ANI" and ".CUR" items in the resources manifest of either the calling assembly or the 'TDHCursorFactory.dll' assembly.


As written/assembled, the 'TDHCursorFactory.dll' assembly contains a number of cursors as embedded resources. Since the class as written is geared towards my overall project, you may well want to eliminate many (or all) of these; and you may want to add your own cursors as resources ... aren't you glad you have the source code?

  • Cursors.arrow_l.cur
  • Cursors.arrow_l_blue.cur
  • Cursors.arrow_l_red-outline.cur
  • Cursors.BlindMouse.ani
  • Cursors.busy_l.cur
  • Cursors.counter.ani
  • Cursors.Cow_chewing.ani
  • Cursors.EarlyBird.ani
  • Cursors.FlyingPig.ani
  • Cursors.HamsterWheel.ani
  • Cursors.HamtonJPig3.cur
  • Cursors.HorseRider.ani
  • Cursors.PanToolCursor.cur
  • Cursors.PanToolCursorMouseDown.cur
  • Cursors.PorkyPig.cur


The TdhCursorFactory.Cursors enum is the means by which the array of Cursors internally managed by the TdhCursorFactory class are accessed. This has both advantages and disadvantages. The main disadvantage is that the only way to add items to the enum is to recompile the class. The advantages are legion, including: the TdhCursorFactory class manages the set of cursors your program is using for you, all you need do is initially set them; you may "override" (or not, as you wish) the standard cursors of the System.Windows.Forms.Cursors class -- your main program's code will be given a valid cursor object in either case; once you are satisfied with *your* version of the TdhCursorFactory.Cursors enum, your version of the TdhCursorFactory class will be both flexible enough to be useful for any program needing color and/or animated cursors and simultaneously specific to your own needs.

The members of the TdhCursorFactory.Cursors enum are :

  • There are a number of members for custom-defined Cursors. By default, the class constructor extracts embedded resources from its assembly for these items, though the main program can replace (or release) any of them at any time. These custom definitions are, of course, geared towards my overall project; you may want to add or remove custom definitions.
    • Cursors._Busy
    • Cursors._Grab
    • Cursors._GrabRelease
    • Cursors._Normal
    • Cursors._X_Random_Busy - a special member; it (randomly) accesses the elements of a "sub-array" of Cursors
  • The remainder of members may be used to "override" the standard Cursors of the System.Windows.Forms.Cursors class. Any to which a Cursor has not been explicitly set (via the [ SetCursor() ] methods) will return (via the [ GetCursor() ] method) the corresponding standard Cursor:
    • Cursors.AppStarting
    • Cursors.Arrow
    • Cursors.Cross
    • Cursors.Default
    • Cursors.Hand
    • Cursors.Help
    • Cursors.HSplit
    • Cursors.IBeam
    • Cursors.No
    • Cursors.NoMove2D
    • Cursors.NoMoveHoriz
    • Cursors.NoMoveVert
    • Cursors.PanEast
    • Cursors.PanNE
    • Cursors.PanNorth
    • Cursors.PanNW
    • Cursors.PanSE
    • Cursors.PanSouth
    • Cursors.PanSW
    • Cursors.PanWest
    • Cursors.SizeAll
    • Cursors.SizeNESW
    • Cursors.SizeNS
    • Cursors.SizeNWSE
    • Cursors.SizeWE
    • Cursors.UpArrow
    • Cursors.VSplit
    • Cursors.WaitCursor

History

  • 2007 October 26: Submission of TdhCursorFactory ver 1.0.001 to The Code Project.
  • 2007 October 27: ver 1.0.002
    • Modified the SetCursor(TdhCursorFactory.Cursors whichCursor, string cursorName, bool caseSensitive) method.
      Previously, if the string cursorName value could not be found in the resources manifest (or did not resolve to a valid Cursor), the method would set the array item referenced by the TdhCursorFactory.Cursors whichCursor value to a null object. Now, there will be no effect.
    • Created the public static System.Collections.ArrayList ResourcesManifest(bool forCallingAssembly) method.
  • 2007 October 29: ver 1.0.003
    • Modified the methods: FromResource() and (one signature of) SetCursor() (sorry about that!)
      - Added the argument "bool forceAsColor" to allow the developer using the class to force ".CUR" files to be loaded via the LoadCursorFromFileW function of "user32.dll." The value of this argument is relevant only for Cursors with the ".CUR" extension; Cursors with the ".ANI" extension are always loaded via the LoadCursorFromFileW function of "user32.dll."
  • 2007 October 29: ver 1.1.000
    • Added the special '_X_Random_Busy' member to the TdhCursorFactory.Cursors enum.
      The '_X_Random_Busy' member may be used to access a "sub-array" of Cursors -- It randomly points to one of the Cursors which have been loaded into the "sub-array." Individual Cursors may be loaded into this "sub-array" via the existing [ SetCursor() ] methods; the [ GetCursor() ] method will randomly return one of the Cursors loaded into the "sub-array."
    • Created the [ InitCursor_X() ] method.
      This method initializes the "sub-array" of Cursors referenced by the enum value TdhCursorFactory.Cursors._X_Random_Busy to a set of pre-defined Cursor objects obtained from the class' resources manifest.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionHow to embed the cursors in resources? Pin
mosquets21-Nov-07 7:53
mosquets21-Nov-07 7:53 
AnswerRe: How to embed the cursors in resources? Pin
Ilíon21-Nov-07 22:53
Ilíon21-Nov-07 22:53 
GeneralRe: How to embed the cursors in resources? Pin
mosquets22-Nov-07 12:14
mosquets22-Nov-07 12:14 
GeneralRe: How to embed the cursors in resources? Pin
Ilíon22-Nov-07 21:00
Ilíon22-Nov-07 21:00 
GeneralLoading from Embedded Resource Pin
Jakka Prihatna1-Nov-07 21:12
Jakka Prihatna1-Nov-07 21:12 
GeneralRe: Loading from Embedded Resource Pin
Ilíon2-Nov-07 2:04
Ilíon2-Nov-07 2:04 
GeneralRe: Loading from Embedded Resource Pin
Jakka Prihatna4-Nov-07 15:56
Jakka Prihatna4-Nov-07 15:56 
GeneralRe: Loading from Embedded Resource [modified] Pin
Ilíon5-Nov-07 17:18
Ilíon5-Nov-07 17:18 
GeneralRe: Loading from Embedded Resource Pin
Ilíon6-Nov-07 7:13
Ilíon6-Nov-07 7:13 
GeneralRe: Loading from Embedded Resource Pin
Jakka Prihatna6-Nov-07 22:49
Jakka Prihatna6-Nov-07 22:49 
GeneralGood But Not Stellar Pin
Mark Treadwell30-Oct-07 0:59
professionalMark Treadwell30-Oct-07 0:59 
GeneralRe: Good But Not Stellar Pin
Ilíon1-Nov-07 12:08
Ilíon1-Nov-07 12:08 
Mark Treadwell wrote:
By way of feedback, ...

Thank you for this eminently helpful and useful feedback. The wise man welcomes helpful and useful criticism. I, myself, have some feedback for you. It is my hope and desire that you will take it in the same spirit in which yours was offered.


1) “Good But Not Stellar
I suppose there is no accounting for taste. For instance, when *I* say that something is “good,” I generally mean that it is on the high side of “average” (though, I must admit to some degree of imprecision, as in some contexts I mean more than that). Apparently, when *you* say that something is “good,” you mean that it is on the low side of “mediocre.”

Also, while *I* never claimed that this class is “stellar,” I will admit to being at least slightly gratified that the first six persons who took a moment out of their busy lives to vote on the article apparently thought that something about it rated a “stellar.” I don’t know; perhaps those six are right and the seventh is just an ass jealous that he didn’t think of writing such a potentially useful class. Then again, perhaps there is no accounting for taste. What do I know, anyway?


2) “… the code still needs lots of work to be considered as a general-purpose library.
Does it now? Could you be prevailed upon to supply me some useful examples of this weakness on my code? Considering that “the code still needs lots of work,” I must suppose that the only limit on your ability to fulfill this request will be the amount of free time you are willing to expend for my benefit.


3) “Currently, it is way too special case.
That may be true … though, I, myself, would quibble over that “way too” business. The fact is that I threw the class together in a few hours over two evenings after work with the primary purpose of serving my own specific needs, and secondarily with an eye towards submitting an article to The Code Project.

So yes, the class does indeed contain special case objects and code. For instance, had it been my goal to write The Perfect General Class, I’d have included no embedded resources in the class itself. Nor do the class’ special-definition cursor names seem to me to be compatible with a goal of The Perfect General Class.

But, it was not my goal to write The Perfect General Class; rather, my primary goal was A Good General Class That Meets My General Needs; my secondary goal was A Good General Class That Other Developers May Adapt To Their Own Needs.

In my (not at all humble) opinion, I achieved my goals. Nearly perfectly. One might almost be tempted to say in a near-stellar manner.


4) “It contains workarounds ("special processing" in the author's words) to handle specific sample cursor files.
It does, indeed. And the in-line comments explain the *why* of it.

In the update I submitted the other evening, even before your so-helpful comments were made (and which I now see has been applied), I have much simplified that special processing. Though, I have not entirely eliminated it. That is, since I know that those two specific cursors *require* that special processing when they are embedded resources (as opposed to files read from disk), and since I (currently) *want* those two specific cursors to be embedded resources of the class as I intend to use it, I still have code to ensure that they are treated properly.


5) “… "Easter Eggs" with different behavior depending on who is logged on …
It does, indeed. As I’ve said, the class is written primarily for *my* purposes.

Now, I *did* intend to explicitly mention those “Easter Eggs” in the article, but I forgot. I also forgot to explicitly mention then in the update I submitted, despite that it was on my mental to-do list. And, considering what a hassle it is to update an article after it has been moved out of “Unedited Reader Contributions,” I much doubt I’ll be updating the article or class again.

So, I suppose that this is the only warning the poor schmucks who *might* have been interested in downloading this class, were it not so mediocre, will possibly ever have. I know that I *always* use free executables, never looking at the source code.


6) “… poor exception handling …
I really *must* beg for specific examples of what I am doing wrong and a demonstration of the right way to do it; I simply know no better.

There is no reason you would know this (or care), but I am entirely self-taught in respect to object-oriented programming in general, and .NET programming in particular. I worked through a couple of those “Teach Your C# in 24 Hours” type books; I read Herbert Schildt’s ‘C#: The Complete Reference’ and now I learn by reading others’ code in interesting-looking projects on The Code Project. I don’t know: perhaps the people in charge of “Special Enhancements” ought to be doing a better job of screening out all the shoddy code. Then, at least, I’d have good … oops, I mean, stellar … code to learn from.

Back when I was being taught how to program, we students had to code via punched cards, and we had to punch the holes ourselves. With sticks (and only the rich kids could afford the sticks that didn’t wear out after half a dozen cards). You kids these days don’t know how easy you have it! Later, I taught myself how to program on-the-fly by toggling switches. May you never have to try to read a (spontaneous, on-the-fly) core-dump when one of the light-bulbs is burned out.

Anyway, and as a matter of fact, there is very little exception handling in the class -- I like to imagine that the code I write is, generally speaking, well enough written that exceptions are, well, exceptional. I understand that some programmers wrap nearly every statement they write in exception handling; the over-head, and the hassle, has never seemed worth it to me.

But, regardless of other programmers’ style, I am more than willing to learn a better style, if you will teach me. Heavens! I do hope it isn’t the code that comes almost directly from the MSDN article that is incorrect.


7) “… lots of commented out code that makes it look like work is still in progress …
Now I know that you’re pulling our collective legs with your idiosyncratic usage of the word “lots:” there are very few statements in the class which are commented out. I will admit that I probably have no consistent pattern to why I comment-out some code and completely remove other code. For instance, in the code which originated in the MSDN article, I commented-out, rather than removed, the code I decided was pointless in the context of the class I was writing.

Is there some Rule of Good Practice (or, should that be “Stellar?”): “Thou shallt never, ever, ever leave commented code in-line?”

When I was being taught to code in COBOL, some of my instructors claimed that it was a Rule of Good Practice that “Thou shallt never, ever, ever use ‘GoTo’.” I disregarded the fools, because even as a rank novice I could see that sometimes ‘GoTo’ is exactly proper.

Now, it is true that outside the ‘TdhCursorFactory’ class proper there *is* the entire (commented-out) code of a class which I’ve been putting together over the last couple of years, for the purpose of extracting objects from an assembly’s resources manifest. Only a few methods of this class are applicable to the requirements of the ‘TdhCursorFactory’ class. But, since I imagine others might find some of that code to be useful, I included it all in a commented-out form.

No doubt, this bloats the size of the resulting compiled library. My bad!

We’re already fairly certain that you are a much better and more experienced .NET programmer than I; so, doubtless, you already have better code to do the same sorts of tasks. Hell, you probably even have a better class to do essentially what the 'TdhCursorFactory’ class does -- for, after all, .NET is a good half-decade old and it never has natively supported animated and color cursors.

Clearly, it’s but an oversight on the part of the “Special Enhancements” folk that there is not one other class/article available on The Code Project to encapsulate the basic function of the 'TdhCursorFactory' class.



8) “… and a potentionally questionable use of mutexes .
Again, I simply *must* beg you to educate me on this matter.

I am aware of only two ways to use the [ lock(object) ] statement: 1) make “object” a reference to the class; or, 2) make “object” a reference to an explicitly defined object -- i.e. no matter what one calls it, is this not a “mutex?”

Perhaps the flaw in my code is that I’m even using the [ lock(object) ] statement in the first place. But no! You faulted the use of mutexes.

Perhaps the flaw in my code is that I should be using the [ lock(object) ] statement for more of the class’ methods. But no! You faulted the use of mutexes.

The only way I can make sense of this helpful comment is that you think option 1) is the correct way to use the [ lock(object) ] statement. I know that I’m ignorant about a lot of things. I’ve often noticed that not everyone is so fortunate in regards to what he does and does not know.


9) “There is some good stuff there, but it is only halfway there in my opinion. YMMV.
Now, see, this is a place where I, personally, would have used the word “lots,” or even “boat-loads,” were I feeling jaunty.


10) “… but it is only halfway there in my opinion.
I am certain we all look forward to your soon-to-be-submitted article on this topic. It’s certain to be stellar … well, so long as you start coding from scratch; it would be such a shame to crimp your style by cribbing my mediocre code.



Conclusion:
Your very informative, helpful and useful feedback would appear to be to boil down to: “Aaaa! I couldda done better!

Now, I don’t doubt that could. But, the fact is, you didn’t. Nor, apparently, did you even try.

There is only one other article on The Code Project which might even begin to be said to be about the same subject matter as this article and mediocre code I’ve submitted: Display Animated Cursors Stored in Resources[^], posted in December of 1999. Its project is written in C++, and appears to me to compile to an .EXE, rather than to a .DLL.

What have you been waiting for, man? You could have owned this concept in relation to .NET.

The only reason I even wrote the 'TdhCursorFactory’ class is that I couldn’t find anything, anywhere. Perhaps, somewhere in the vastness of the internet, there exists The Perfect General Class to perform this function; I decided that it looked like it would take me less time to write a Good-Enough General Class than to find that hypothetical Perfect General Class.


YMMV
Indeed.

In my not-at-all-humble opinion, your mileage is indistinguishable from 0.0


Codicil:
As even you must by now suspect, I can be slightly sarcastic when I deem it appropriate. Though, I do have to step outside my comfort-zone to do so. Ah, well, it’s a good thing to stretch one’s abilities, isn’t it?

There is a certain class of person that I do not suffer gladly: even if it happens that the sort of person who signs himself “Special Enhancements” turns out to be one of that special class, I am most unlikely to suffer in silence.

Dude, you *earned* this sarcasm -- not because you criticized my code (I believe I’m man enough to deal with that), but because the criticism is almost entirely pointless, and the few points are worthless to me as a means of improvement. Nor can I see that anything you’ve said is remotely useful to others who may be interested in downloading this project.

But, at least you aren’t the ass who voted Ri Qen-Sin’s comment a ‘2.’ Or are you? (That was a rhetorical question. And, if you are, don’t answer it: I’d hate to have a low opinion of you; that particular no-class fool is the lowest of the low).
GeneralRe: Good But Not Stellar Pin
fwsouthern1-Nov-07 15:25
fwsouthern1-Nov-07 15:25 
GeneralRe: Good But Not Stellar Pin
Ilíon1-Nov-07 16:31
Ilíon1-Nov-07 16:31 
GeneralRe: Good But Not Stellar Pin
fwsouthern1-Nov-07 16:36
fwsouthern1-Nov-07 16:36 
GeneralRe: Good But Not Stellar Pin
Ilíon1-Nov-07 16:38
Ilíon1-Nov-07 16:38 
GeneralRe: Good But Not Stellar Pin
Mark Treadwell1-Nov-07 16:46
professionalMark Treadwell1-Nov-07 16:46 
AnswerRe: Good But Not Stellar Pin
Mark Treadwell3-Nov-07 16:01
professionalMark Treadwell3-Nov-07 16:01 
NewsRe: Good But Not Stellar Pin
Ilíon3-Nov-07 18:18
Ilíon3-Nov-07 18:18 
GeneralRe: Good But Not Stellar Pin
Mark Treadwell3-Nov-07 19:18
professionalMark Treadwell3-Nov-07 19:18 
NewsRe: Good But Not Stellar Pin
Ilíon3-Nov-07 18:43
Ilíon3-Nov-07 18:43 
General5 Thumbs Up! Pin
Ri Qen-Sin27-Oct-07 3:35
Ri Qen-Sin27-Oct-07 3:35 
GeneralRe: 5 Thumbs Up! [modified] Pin
Ilíon27-Oct-07 6:30
Ilíon27-Oct-07 6:30 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.