Rumours of my death have been greatly exaggerated
Trying to figure out some long term plan of action, as well as get a proper perspective of what I am going to do. I’m sick of taking whatever crappy job I can get, when there are software developers making a nice salary that I could easily program circles around. Even a job working as some sort of IT thing would be good.
Anyway, I’ve been picking up some freelance jobs off freelancer.com; my first job was somewhat dissappointing, I worked for three+ months on the project for a relatively paltry 500 or so dollars. It’s something, but it’s not worth three months of work. Of course if I can sell it to others, that might make it more worthwhile.
But I do not think trying to sell it via my site, like BASeBlock, would be a good idea. Nobody has purchased BASeBlock (I’m starting to wonder if maybe my paypal button broke in the meantime), and that’s 5 dollars; BCJobClock, the application in question, is more “enterprisey” And would probably be priced quite a bit higher, by virtue of being designed for use in businesses.
One consideration I had was to contact a nearby software dev shop that I know of in my area, Pelican Software (http://www.pelsoft.com), Currently, they have two products. But I’ve also heard (rumour, to be fair) that the company is struggling. I drafted a E-mail that details some of the market conditions I feel might be working to their detriment, such as their products being more programmer time intensive (being written in C++). A small dev shop should utilize their “agility” by using fast, rapid development languages like Ruby, Python, Perl, etc. I also offered BCJobClock as a possible piece of software they could license in some fashion. Their current products, Tallys! and Books! could be supplemented by BCJobClock, which could be called Clocks! (I don’t really like their weird naming scheme but “a rose by any other name…”). Another point of note is that Tallys!, their existing product, deals in a business situation where BCJobClock might also be useful, so there is a “foot in the door” so to speak. One could argue they are somewhat tangential, but tally’s deals with managing inventory, whereas BCJobClock deals with managing time. BCJobClock was originally written for use in a Repair shop, but it’s facilities naturally extend to pretty much any sort of application for tracking employee time working on various disparate tasks.
If you ask me, too, BCJobClock actually works pretty bloody well. I just fired up the administration applet, and came very close to forgetting that I wrote the application. Same for the monitor app and the Client-touchscreen program. These three components of the larger application represent a significant time investment I could have otherwise spent on something else. Or not at all. I got some ROI in the form of the price of the product as received by the freelance client, but I think the application- (And, to my understanding the client does as well) could find a significant userbase. I’ll probably draft out the E-mail and sent it off sometime soon; I’m considering creating a “marketing” page with more up to date screenshots of the application and it’s functions that I could point them too.
It’s a fine piece of software, I just have no good way to distribute it. Worst case scenario, I’m forced to plonk it on the main page and make absolutely no sales, simply because the application is not discoverable to those who could find use in it. If I’m lucky, Pelican Software will see that my idea could have mutual benefit, if not, no harm no foul.
I just realized that this is pretty much the first and only time I’ve actually mentioned BCJobClock to any significant capacity. I’d go into more detail, but the best I think I can do is point at this .
It’s done- at least, It works and I can’t think of any features to add at the moment, so it’s functionally complete. I just don’t have anywhere to put it, aside from this site. The employer for whom I wrote the application said they were going to show their POS vendor; that was a few months ago, and I think something has come up with them since they have become quite incommunicado as of late. (And haven’t released the last milestone, either…). Basically, this sort of leaves me with this functionally powerful database driven Line of Business application, but no way to get it to customers. I could put it here, but this site doesn’t get nearly the coverage it would need, certainly not from the sorts of places that will get the most use out of the software. That, and I’d probably have to create some new “site” for the Software Solutions label, giving it a more “business” feel.
Despite my ramblings to the contrary, I have decided to make some of my applications “commercial” or at least paid-for.
Not entirely, though; Instead, I’ve, at least for the moment, decided on a “almost everything works except for a few things” method. In this case, for BASeBlock, the Editor will work fine, but will be unable to save to a file.
There are some important considerations I took while developing my current solution:
The second point is something of an opposite stance compared to what you usually find with “DRM” or similar measures. I figure that a user who paid accidentally being marked as unregistered is going to be a lot worse than a unregistered user being able to appear as a registered one to the program, so in a few cases where there is a bit of confusion, the program just proceeds as licensed. The “Protection” I use is more or less obfuscation, and rather weak obfuscation at that. Anybody with a decompiler will be able to figure out how I generate the keys, but if they are willing to do that to use my software than I feel I ‘won’ anyways.
By far the simplest, or, rather, easiest to implement, method of software protection is to make it so that you hash a few unique pieces of data for a user into a “Product Key” using a “secret” method. In my case, I use three pieces of string data; the User name, Organization, and the Product Name in question. The idea is to take these three strings and create a “Product Key” string out of them. My relatively simple (and probably easy to reverse engineer) method, when given values for User Name, Organization, and Product Name, spits out something like P6WI-CKEC-RJ5F as a product key.
The basic idea is that the application, naturally, is initially “unregistered”. When it is unregistered, it will normally prompt for registration information at start-up. In BASeBlock, the code being used for license-checking is fairly short:
The call to NetCheck is current dev code that I’m trying out to make it consult my web site to find out if the key in question is locked out or something. (if it discovers that it is, the data in the registry will be deleted). Afterwards, it checks if “BASeBlock” is registered. Each Licensed BASeBlock Application will store it’s registration information in the registry; or rather, the update library will store it. If it isn’t registered, it calls the Update Library and asks it to show the “Register” dialog. This dialog accepts the username, organization, and Product Key- the last one of which ideally I will be providing to each user as purchases are made, or given away when I finally give up on the entire idea. It uses the same code to generate the key from the username, organization and application name, and compares it to what it is given in the dialog. If so, it stores that data in the registry (which will be inspected in future sessions) and returns. Note that immediately after, BASeBlock again calls the “IsLicensed()” routine- this is because if the registration was in fact valid, it will now be true whereas before it was false.
Currently, the implementation of the “lock-out” is trivial- if it’s not licensed, it throws an exception or shows a dialog. However, this is, as I said, trivial to overcome. Something I’ve been considering is to make it so that the unregistered version literally doesn’t have the save function at all- that is, the code simply isn’t there. The best way I can think of to do that would be to actually have that as part of a separate assembly that is loaded at run-time. Ideally, the code to do this would be something like this:
[code]
[BCUpdateLib.ProtectedFunction("BBLocked","DoSave")]
private void DoSave()
{
//Code for saving Levels here
}
[/code]
But needless to say things aren’t that simple. For one thing I don’t think you can simply have an attribute magically create a new assembly. For another, even if I assume it is possible (and really, with enough effort and research almost anything is) the code will no doubt be quite complex, and I prefer to keep things simpler if I can.
In any case, the core concept is that the protected functions will be in separate assemblies, and those assemblies will be encrypted using the product key. This will occur at my end- I will be sending these files to users along with their product key. (which means I should probably try to keep the functionality contained therein as short as possible) The Registration dialog will have Browse… dialog, or allow drag-drop, etc to reference the “key” file, which will be stored in a central location (perhaps %appdata%\BASeCamp\Licenses or something).
When the application is loading, it will call a static “LoadProtectedAssemblies()” Function, or something similar, within the Update Library. This will enumerate the “key” files, which will be decrypted using a Product Key generated from the username, organization, and product name for the product in question. If the result is a valid assembly, load it, otherwise we clearly can’t. Later in the code, the Editor goes to save and calls a static routine in the Update Library, which will attempt to find the appropriate assembly and if none is found throw something like a “unlicensedCodeException” or something similar. This could have an interesting tie-in with the current code that enumerates various assemblies; any decrypted assemblies could be tossed into the array for inspection. This would allow me to stick various other classes that implement certain interfaces or derive from specific classes, like Block, or iLevelSetBuilder, into a assembly, and encrypt them in this fashion, and they will only work for “licensed” users of the program. At the moment though, even though the licensing code has worked well for me so far I’d rather keep it from getting it’s paws on everything.
After much mulling over it, I have decided that BASeBlock 2.0 will be “shareware” sort-of. This version will add a numbectr of new blocks, loads of bugfixes, and even fix the high-scores to work properly, which should have been simple but was dastardly to remedy.
What I mean isn’t that it will actually be shareware but rather that the program will be free but some parts of it will require “registration” to unlock. In BASeBlock’s case I’ve decided that the entire application will be free, along with almost everything that comes with the game, including the editor.
The difference is that the editor will be “crippled”- you can create and edit LevelSets and test them with the main game, but you cannot save them to a file unless the game is registered.
DWM
The “protections” will be relatively simple, and almost surely a breeze to crack. I plan to document some of it, in fact. I might utilize the otherwise dead-code that is part of the new licensing component to release encrypted .reg files that are specific for each user’s key and will only decrypt properly with the right key(making it difficult to work around by simply inserting a few jumps or skipping code or something)
The original plan for BASeBlock was to make the entire thing free; but it represents a lot of work- Graphics, some of the music, sound effects, etc. and I haven’t gotten anything monetary out of it yet. It’s not a particularly good breakout clone but it has it’s merits. loads better than my previous attempt, Poing, which is embarassing in comparison. It’s certainly no Ricochet Lost worlds (A fine game and one I highly recommend if you have any interest in the “block and ball” type genre), but then again, I’m only one person, right?
Basically, I’ll add code for simple protection to try to prevent casual piracy (well, really casual piracy) but anything more than that and I risk screwing up when the game is in fact legitimately obtained; which is something I absolutely will not tolerate.
I see this question semi-frequently on forums. It’s a reasonable question on the surface. However, the fact is that there is no “Best language for a beginner”. Truly, the very idea that a given computer language could be “better for beginners” than another is downright assinine.
Consider human languages. A person learns language over time, and there isn’t any more difficulty for different languages; the skill develops through practice. Chinese isn’t “harder” to learn than English, for example; but it is harder to learn when you know english.
So how does this extend into computer languages?
Well, the first computer language you learn won’t matter, just as the first Human language you learned doesn’t really matter.For Human languages, the big thing you are learning is how to express yourself to others. For Programming languages, the big thing you are learning is how to express yourself- to the computer.
Once you learn one imperative programming language, the others are easier to learn; same way with human languages. Once you know one germanic language, the others are typically easier to learn.
Of course, it’s harder to learn Chinese or Japanese when you are used to a latin alphabet; for programming languages, this “barrier” is typically found between imperative, Declarative, and functional languages. of course the actual difficulty is not quite at the same level; but functional languages are fundamentally different in many ways from imperative languages, enough that trying to take what you learned via programming in an imperative language and applying it to a functional one can do more harm than good to your learning process, just as trying to apply your understanding of English will harm attempts to learn most non-germanic languages, trying to apply an understanding of Chinese/Japanese/etc to learning English will harm attempts to learn it as well.
Additionally, one issue I find is that many people will say that “language X is easy to learn because it’s like plain english”. Which is a flawed perspective, since that brings with it a lot of language baggage; english is designed for communicating between people; a programming language is designed for communicating between a person and a computer (or rather, the interpreter/compiler which makes it into something the computer understands, but let’s not cloud the issue). So you end up with a psuedo-english language that tries to be declarative but at the same time isn’t english; SQL, for example, is english-like, but I’d be hard-pressed to say that “Select * from Customers Where CX>6″ is “plain english”. It’s easy to understand, but it’s restrictive; after all, in english the same concept could be expressed as “choose all fields from the customers table where the record in question has a CX field greater than 6″. But that is far from valid SQL, which has a far more restrictive grammar and syntax. (if it didn’t, parsing it would be a nightmare).
This is how I’ve always felt about it. What is important isn’t what specific language you learn but that you learn the concepts involved; for imperative languages this would be references, functions, recursion, variable allocations,object mutability, (and for OOP languages the various OOP concepts, such as polymorphism, aggregation, composition, delegation, etc). Functional languages, (and some imperative languages that integrate functional features) it’s things like lambdas, recursive definitions,Higher-order/First-class functions (Functions that take other functions as arguments), pure functions, strict versus non-strict evaluation, catamorphism, etc.
Once you learn the concepts, you can use pretty much learn any language with minimal effort, you just need to learn the syntax.(unless you are jumping across a declarative/imperative/functional divide, in which case you also need to learn and relearn other concepts as well). Overall, however, Learning a syntax is easy; the first programming language you learn is hardest no matter which one you choose simply because you have to learn the syntax at the same time you are learning all sorts of “new” concepts. It doesn’t matter what language you choose; it will always be “harder” to learn than later languages for you.
It has been mentioned that PASCAL, a fictitious language, apparently contradicts my points here. The argument being that languages that are easier to write functionality in will be easier to learn.
However, this misses the point. The ease of learning of a first programming language is absolutely pointless, because it isn’t the syntax or structure of a given language that gives you the tools to coalesce those language elements into algorithms, and therefore solutions, but rather your understanding of base concepts. The argument for PASCAL (again, a fictitious language that doesn’t exist, evidently they truly meant Pascal) was essentially that it needed less code to read and write to the console. For example:
is more “concise” and “easier to learn” than the equivalent java code:
The argument essentially rests on the faulty premise that Writeln() is somehow “easier to learn” than java.out.println(). What such a perspective fails to take into account is the fact that Pascal and java are semantically quite different and based off of different programming models. Pascal is a structured programming language that divides it’s functions into units, but doesn’t (except in later incarnations such as Object Pascal and Delphi) support Object Oriented programming concepts.
This can be examined by merely looking at, say, the Writeln() function. It has more than one argument, and if the first of those arguments is a file handle, the output is written to that file. The requirements for creating and opening a file are less than easy- for example, a file is opened using the Rewrite() function, after you call Assign() to assign a file name to the file handle. Memorizing otherwise arbitrary function names and how they fit into a number of contexts is hardly easier to learn. Java, being Object Oriented bases it’s run-time library on Objects. the System class has a number of static fields that expose a number of System level objects; the “out” field represents the standard output stream, and is an output stream object, in fact; therefore in order to write to the standard output stream, things can be more verbose. In the case that a routine needs to repeatedly access and write to the output stream, it can easily be cached in a local variable- or really any variable at all. The point is that neither language makes it easier to learn the concepts required to implement algorithms. Java has a relatively basic implementation of Object Orientation (it is missing multiple Inheritance, proper generics, functions as objects, and metaclasses), and Pascal is a good implementation of the structured programming paradigm. Object Oriented concepts build upon structured programming concepts, and since you would have to learn the former first, one could argue that Pascal might be a better choice. However, there is still the crux of syntactic difference; additionally, being exposed to Object oriented syntax early on- even if one doesn’t understand it- could make it easier to absorb the concepts behind those peculiarities later on.
Of course, Pascal isn’t a modern language; it’s modern Equivalent, Delphi, fully supports Object Oriented Programming- even better than Java ever will, in fact- but that doesn’t mean it’s either a good or bad choice for a programming language to initially learn. I stick to my original perspective that it doesn’t really matter what language a person learns, what is far more important is they stop beating around a bush on some decision that they think is important and make it. It’s like debating over what type of cake a person should eat first to properly have the cake experience. Thing is- chocolate, spice, vanilla, fruit, etc. Whatever cake one chooses, it’s all cake and your experience is going to initially be coloured by that first cake. The only way to properly experience what a “cake” is is to have a variety of different cakes- the one you eat first is irrelevant. Same with programming languages; the only way to properly experience all the concepts and idioms involved is to learn a variety of different languages. The first one is going to always be a barrier because you have to become accustomed to the more strict grammars and syntax used with programming languages. Unlike a human language- such as english, where misspellings or grammatical ambiguities might confuse the reader or get you weird looks or a laugh here and there, with programming languages the interpreter or compiler is going to take everything you say literally and if it cannot understand what you are saying it will get very cross. Some compilers will put up with more ridiculous constructs- for example, C++ will happily compile code that makes absolutely no sense even to the most trained C++ programmer (and the result makes an equal amount of sense); others are restrictive, and will verbally assault you if you miss a single letter (Pascal, Delphi) others try to help you by doing stupid shit and inserting syntactic characters where it thinks you might need them (javascript). Anyway, my point is, such details aren’t important; the base concepts are there in all languages, just like all cakes are made with certain base ingredients and the unique flavour is added to the cake batter and supplemented (in most cases) with frosting.
In some of my recent posts, I’ve covered the topic of accessing and parsing an INI file for configuration data in a C# Application.
Some may wonder why. After all; the “norm” for C# and .NET applications is to use XML files for configuration information, isn’t it? Well, yes. But to be honest, XML files are a fucking pain in the ass. They aren’t human readable to your average person the same way an INI file is, and getting/setting values is tedious. Primarily, the reason I use INI files is that they are:
Mostly, I feel that XML, and in many ways other configuration options, are more or less driven by fad. Another option for configuration settings on Windows is the Registry, which is in fact often the recommended method; but this is anything but accessible to the user. Would you rather guide a user to edit a INI file or to fiddle with registry settings?
With that said, INI Files do have their own issues. For example, their data is typically typeless; or, more precisely, the Values are all strings. Whereas using a .NET XML Serializer, for example, you could easily(relatively speaking) serialize and deserialize a special configuration class to and from an XML file and preserve it’s format, with my INI file class there will typically be some work to parse the values.
It was with the idea of turning my string-only INIFile configuration settings into something that can be used for nearly any type that I created the INItemValueExtensions class, which is nothing more than a static class that provides some extension methods for the INIDataItem class. I covered this in my previous post.
The prototypes for the two static functions are:
How would one use these extension methods? Well, here’s an Example:
Woah, hold the phone! What’s going on here? We’re loading DateTime values directly from the INI File? How does that work?
All the “magic” happens in the getValue
If it does implement a TryParse() routine, (like, for example, DateTime) it doesn’t try quite as hard. It takes the string from the INI file and hands it to the Type’s TryParse() routine, and then returns what that gives back. Naturally, the inverse function (setValue) does something somewhat opposite; it checks the Base64 logic, and if so it sets the value of the item to the Base64 encoded value of the serialized object. Otherwise, it just uses toString().
This typically works, particularly with DateTime, because usually ToString() is the inverse of TryParse(). In the case of DateTime, this has a few edge cases with regards to locale, but usually it works quite well. And more importantly, the introduction of allowing any object that implements ISerializable to simply be thrown as an INI value via a Base64 encoded string is useful too, although with large objects it’s probably not a good idea for obvious reasons.
Of Course, an INIFile is only one of any number of ways to store/retrieve configuration settings. And while they don’t typically lend themselves to the same syntax provided by the INIFile class, it would be useful to have some sort of common denominator that can handle it all. That was the original intent of the relatively unassuming ISettingsStorage interface:
This uses a concept known as a “category” which is pretty much the same idea as an INI File section. What makes it different is that, for implementors that use other storage mechanisms, it could have additional meaning; for example, a fictitious XML implementation of ISettingsStorage could use the “Category” string as an XPath to an element; and the Value could be stored/retrieved as a Attribute. a Registry implementation might use it as a Registry path, and so on.
The problem is, even though the INIFile class implements this interface, it’s too basic, and doesn’t provide nearly the syntactic cleanliness that just using the INIFile does. Stemming from that, and because I wanted to try to get a way to store settings directly in a DB, I introduced two events to the INIFile class; one that fires when a Value is retrieved, and one when a value is saved. This way, the event could be hooked and the value saved elsewhere, If desired. Now, to be fair, this is mostly a shortcoming of my interface definition; as you can see above, there is no way to, for example, inspect category or Value names. I toyed with the idea of adding a “psuedo” category/value combination that would return a delimited string of category names, but that felt extremely silly. The creation of a generic interface- or abstract class- that provides all the conveniences I currently enjoy using my INIFile class but allowing me to also use XML, Registry, or nearly any other persistent storage for settings will be a long term goal. For now, I’m content with accessing INI files and having a unclean event to hack in my own behaviour.
My first test of the above feature- whereby it allows values to be TryParse’d and ToString’d back and forth from a given type on the fly- was the creation of a FormPositionSaver class.
The proper way to save and restore a window’s position on Windows is using the GetWindowPlacement() and SetWindowPlacement() API Functions. These use a structure, named, quite aptly, “WINDOWPLACEMENT” to retrieve and set the window position and various attributes. Therefore, our first task is to create the proper P/Invoke’s for these functions:
I also include OffsetRect(), but I’ll get to that in a bit. Now the “big one” is the definition of the WINDOWPLACEMENT structure and it’s various aggregate structures. Why? well, in the interest of leveraging the INIFile’s static extensions, Why not define a static TryParse() and a toString() method on the structure that can set and retrieve the member values:
WHEW! that’s quite a bit of code for a structure definition, but we’ll make up for it with the brevity of the actual FormPositionSaver class itself. First, my design goal with this class was to make it basically do all the heavy lifting; it hooks both the Load and Unload event, and saves to and from a given INIFile Object in those events. Since the application I was working on at the time didn’t actually get a Valid INI object until during it’s main form’s Load event, and since there is no way to say “Invoke this event first no matter what” I also added a way for it to be told that hooking the load event would be pointless since it already occured, at which point it will not hook the event and instead set the form position immediately. Values are stored
Alright, so maybe I lied a bit. It's not super short. Although a lot of it is comments. Some might note that I only sporadically add doc comments, even though I ought to be adding them everywhere. Well, sue me. I just add them when I feel like it. When I'm concentrating on function, I'm not one to give creedence to form.
This is where I explain OffsetRect(). Basically, if your application is run twice, and you load the form position twice, the second form will open over the first one, and the screen will look pretty much the same. So we detect previous instances and offset by an amount to make it's position different from any previous instances as necessary. That's pretty much the only purpose of OffsetRect.
I have packaged the current versions of cINIFile.cs and the new FormPositionSaver.cs in a zip file, it can be downloaded from here .
HAHA! How’s that for a clever title?
Oh… well… ahem… nevermind.
As a avid user of my own INIFile class, which I first write about- at least it’s C# implementation- in my parsing INI files posting , I am always looking for ways to improve it’s usage make it more “accessible”.
Recently, I have been tasked (by way of my new title of “freelance consultant”) with creating several LOB (Line of Business) Type applications. Applications, naturally, have a tendency to lend their implementations to the creation and reading of settings. Being something of a fan of the simplicity of INI Files, I chose to use my INIFile class in the application. It works well, however, I have noticed that I have a lot of duplicate code. More specifically, I typically have to implement a “wrapper” class, which manages configuration information and reads/writes values to and from the INIFile as its own properties are accessed. For example:
Nothing too dreadful, but imagine having nearly the exact same thing repeated a number of times! The code is repeated and as Larry Wall says, one of the traits of a good programmer is sloth. I don’t like having to write this same code over and over again! The INIFile is supposed to make it easy!
The trouble here stems from the fact that the INIFile values are only strings; and typically, many settings are represented in the application itself as integers and booleans, dates, and so forth. My first attempt to mitigate the clutter was a static method, which I called xParse:
relatively straightforward- basically it’s a shell of what I had repeated over and over again. This mitigated the issue somewhat, so my properties in the wrapper looked like this:
much more managable, but still, could we not make this more concise? My first thought, was that perhaps I could eliminate the necessity of having the wrapper at all; I recalled two interfaces from my old COM programming days, specifically, IDispatch and IDispatchEx. Surely, I could do something similar?
Unfortunately, the interfaces are for COM, and C# doesn’t have dynamics until Version 4.
So, I fired up Visual Studio 2010 express to see if I couldn’t add the dynamic language constructs to the INIFile class; additionally, since I still need to work with .NET 3.5, I’ll add the new code as a conditional compilation.
The first step was deciding exactly what I wanted to happen. Imagine code like this:
The holy grail of the INIFile simplicity! Naturally, the .NET framework does provide the facility with which to add this functionality, as part of the System.Dynamic namespace.
The first step was deciding on the method by which to conditional compile. Since projects copy the source of a file to your project folder when you add them, it seemed reasonable to simply add it as a #define right inside the INIFile class itself.
#define CS4
And now, I just need to enclose all my new happy stuff in a conditional directive, and I’ll get the best of both worlds- C# 4.0 consumers who keep the #define will be able to use the suave new feature, and older consumers will still be able to work without ripping apart the classes. The code to add this was surprisingly simple; as it stands now the longest method (An implementation of TryDeleteMember, which is never called from C#/VB.NET consumers, so is excessive for my usage). First, obviously we enclose the import statement in the conditional compile; the class headers are conditionally compiled as well, only deriving from DynamicObject with CS4 set.
The core of the new functionality is in the overrides to the Dynamic Object’s TryGetMember.
For the INISection:
And for the INIFile…
Exactly the same, in fact. This works because of the indexer I added; the indexer will add the item if it doesn’t exist and return the new value, so even if the member name doesn’t exist, the INIFile will simply have that section added.
That’s for the retrieval of erements; to allow the assignment to them in the same fashion, we need to override TrySetMember(). In my case, this was a bit more involved, for flexibility purposes.
For example, code like INIFile.MainSection=”hello” should work, and change the name of the section. And why allow things like assignments from a Dictionary<String, String>, or maybe even a list (assigning a numbered id to set values)? And of course allow setting the Value directly, which will likely use the indexer much as I did for the TryGet… Implementations.
setting the Value should be equally flexible; since we can, why not?
for example, why not make the following “legal”?
The first example sets the Value to a string, the second sets it to a DateTime that is silently casted to a String (using toString(), and the last two use the new C# 4.0 tuples, to set both the name of the value and the value simultaneously.
A more elegant solution would be to add this code to the Indexer, and merely call the indexer with the name and the value and return true if no exception occurs and false otherwise. However, I’m reluctant to go that route since some of the types are C# 4 types (Tuples).
So Now, I’ve got an INI File implementation that supports Dynamic invocation. Well, that’s great… except that the application I first found it clumsy in is using .NET 3.5, so I can’t use the dynamic features. Back at square one.
In C# 2008/3, we might not be able to leverage the power of dynamics, but we do have generics and Extension methods at our disposal. a feasible alternative could be to add a extension method to the INIDataItem class that has a generic type parameter that it will attempt to convert it’s string Value into. First, using ChangeType, second, it can try to invoke a static TryParse on the given Type to parse the “value” string. And if none of that works, it can return a passed in default. This is still more verbose than the dynamic solution, but it has two distinct advantages- first, it’s type-safe, so you get all the intellisense goodness, and second, it’s still shorter than the alternative.
Here is the code, which can be found in the cINIFile.cs file attached to this posting as well.
And there you have it, a bunch of awesome additions. INI files are often thought of as deprecated, but that’s only the INIFile functions. This class was designed because working with the registry makes it difficult to test properly, and because JSON,YAML, and many other formats are excessively complicated. when you just need a few basic settings, all you need is the clean, simple format of a INI file. And now, with these additions, code for reading from those INI files is clean and simple as well!
As I posted previously here , Sorting a Listview can be something of a pain in the butt.
In that article, I covered some basics on providing a class that would essentially give you sorting capabilities for free, without all the messy code that would normally be required. A lot of the code required for sorting is mostly boilerplate with a few modifications for sorting various types. As a result, the generic implementation works rather well.
However, as with any class, adding features never hurts. In this case, I got to thinking- why not have right-clicking the ColumnHeaders show a menu for sorting against that Column? Seems simple enough. I quickly learned that apparent simplicity often is misattributed.
I faced several issues. The first thought was that I could hook a Mouse event for Right-Clicking a column header. Unfortunately, I soon discovered two facts about the .NET ListView control. First, was that there was no event for right-clicking a header control. Second, no even was fired at all by the ListView control when you right-clicked a header.
This left me stymied. How the heck do I implement this feature? I discovered something of a “hack” however, in that when the ListView’s ContextMenuStrip property is set, that ContextMenu Strip will be shown regardless of the location the ListView is clicked. This at least gave me something to work with. Since a ContextMenuStrip’s “Opening” event can be easily hooked, we can use that as an entry point and perform needed calculations to determine if we are indeed on a columnheader.
Which brings me to the next problem, which is determining when a columnheader was in fact the item that was clicked. This requires determining the rectangle the Header control occupies, first. The Header Control is a child control of the ListView; as such, a platform Invoke using the EnumChildWindows() API was required, something like this:
private Rectangle _HeaderRect;
private delegate bool EnumWindowsCallBack(IntPtr hwnd,IntPtr lparam);
[DllImport("user32.dll")]
private static extern int EnumChildWindows(IntPtr hwndParent,EnumWindowCallBack callbackFunction,IntPtr lParam);
[DllImport("user32.dll"]
private static extern bool GetWindowRect(IntPtr hWnd,out RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
private bool EnumWindowCallback(IntPtr hwnd, IntPtr lParam)
{
RECT rct;
if(!GetWindowRect(hwnd,out rct))
{
//first child of the listview should be the header control
_HeaderRect=Rectangle.Empty; //likely the listview is not in Details mode, so there is no header control.
}
else
{
_HeaderRect = new Rectangle(rct.Left,rct.Top,rct.Right-rct.Left,rct.Bottom-rct.Top);
}
return false; //cancel enumeration.
}
private static ColumnHeader [] GetOrderedHeaders(ListView lvw)
{
ColumnHeader [] returnarray = new ColumnHeader [lvw.Columns.Count] ;
foreach(ColumnHeader loopheader in lvw.Columns)
{
returnarray [loopheader.DisplayIndex] = loopheader;
}
return returnarray;
}
Quite a bit of boilerplate to add in. Basically, the idea is that we will hook the contextMenu Opening event of the Listview, (and we add a context menu to hook if the listview in fact doesn’t have one) in our constructor; and then when we receive the event we need to determine if the click occured within the area of the header control of the listview, if so, we cancel the event (which stops the default context menu from appearing) and show our own menu for the columnheader, which we can acquire using a bit of math and the static “GetOrderedHeaders” function, which retrieves the array of columnheaders of a ListView in order of appearance Left to Right (since the user could rearrange the Columns).
So First, we need to add code to the GenericListViewSorter’s Constructor. We also have a few private variables that are added; in this case, we need a ContextMenuStrip variable called “_ghostStrip” which we will use if we need to create a context menu for the control, since we don’t want that to appear in the default case. Of course we create our own ContextMenuStrip which we will show in the event instead of the default when appropriate. so we add this beneath the existing code in the constructor:
if(handleListView.ContextMenuStrip==null)
{
handleListView.ContextMenuStrip = new ContextMenuStrip();
handleListView.ContextMenuStrip.Items.Add("GHOST"); //add a ghost item so we get the Opening Event
_ghoststrip = handleListView.ContextMenuStrip;
}
//create OUR context menu
_headerContextMenuStrip = new ContextMenuStrip();
//add a ghost item to make sure Opening will fire.
_HeaderContextMenuStrip.Items.Add("ghost");
handleListView.ContextMenuStrip.Opening += ContextMenuStrip_Opening;
handleListView.ContextMenuStripChanged += handleListView_ContextMenuStripChanged;
Of course we need to add the two referenced event handlers, too. The ContextMenuStripChanged being a rather simple implementation designed to keep changes in the contextmenu of the listview from causing us to balls up and stop showing ours (since we are now hooking a orphaned context menu not being shown by the listview).
void handleListView_ContextMenuStripChanged(object sender,EventArgs e)
{
OurListView.ContextMenuStrip.Opening+=ContextMenuStrip_Opening;
}
Now the meat of the code is in the ContextMenuStrip_Opening() routine. This will need to determine wether its applicable to show the Column menu, or the already present menu (which it doesn’t show either if it happens to be the _ghoststrip). This is accomplished by use of the GetCursorPos() API routine paired with the already present GetWindowRect() implementation, which we update by calling EnumWindows.
void ContextMenuStrip_Opening(object sender,System.ComponentModel.CancelEventArgs e)
{
//first, get screen coordinates of Cursor.
POINTAPI gapi;
GetCursorPos(out gapi);
Point gotposition = new Point(gapi.X,gapi.Y);
//acquire the HeaderRect of the control...
EnumChildWindows(OurListView.Handle,new EnumWindowCallBack(EnumWindowCallback),IntPtr.Zero);
//if the mouse position is within the retrieved rectangle, cancel the display of the normal menu and create and show ours.
if(_HeaderRect.Contains(gotposition))
{
e.Cancel=true;
int xoffset = gotposition.X - _HeaderRect.Left;
ColumnHeader clickedheader = HeaderAtOffset(OurListView,xoffset);
if(clickedheader != null)
{
//create the context menu as needed.
_HeaderContextMenuStrip = new ContextMenuStrip();
_HeaderContextMenuStrip.Tag = clickedheader;
//two items, one for ascending order, one for descending order.
ToolStripMenuItem AscendingHeaderItem = new ToolStripMenuItem(String.Format("Sort Column \"{0}\" Ascending",clickedheader.Text));
ToolStripMenuItem DescendingHeaderItem = new ToolStripMenuItem(String.Format("Sort Column \"{1}\" Descending",clickedheader.Text));
//if the current sort column is the header, check it off and disable it.
if(CurrentSortColumn == clickedheader)
{
if(OurListView.Sorting ==SortOrder.Ascending)
{
AscendingHeaderItem.Checked=true;
AscendingHeaderItem.Enabled=false;
}
else if (OurListView.Sorting==SortOrder.Descending)
{
DescendingHeaderItem.Checked=true;
DescendingHeaderItem.Enabled=false;
}
}
AscendingHeaderItem.Tag = ClickedHeader;
DescendingHeaderItem.Tag = ClickedHeader;
//set event handlers for the two items.
AscendingHeaderItem.Click+= AscendingHeaderItem_Click;
DescendingHeaderItem.Click+= DescendingHeaderItem_Click;
//add them to the context menu strip.
_HeaderContextMenuStrip.Items.Add(AscendingHeaderItem);
_HeaderContextMenuStrip.Items.Add(DescendingHeaderItem);
//display the menu.
_HeaderContextMenuStrip.Show(gotposition);
}
}
else
{
//show the default menu, but only if it isn't the ghoststrip.
if(OurListView.ContextMenuStrip == _ghoststrip)
e.Cancel=true;
}
}
The events for the two buttons basically sort based on the columnheader in their tag, nothing particularly special there. the actual details can be seen in the source file itself, really.
It actually works quite well, I’m using it in a production application, and it’s working quite well.
Some obvious enhancements, of course, include making it possible to customize the shown menu, to present other options; perhaps a delegate or event that can be hooked that is given the Strip and the clicked column, and any number of other parameters? This would essentially give the equivalent of a ColumnHeaderRightClicked type event, too.
Or, at least that’s what I am calling it. The .NET framework provides quite a rich set of data structures for dealing with Dates. You’ve got DateTime which represents a single point in time, You’ve got TimeSpan which represents a interval.
However I noticed something somewhat absent- a DateTime Range, with a start time, and an ending time. This came about because I required a way to coalesce a set of DateTime’s organized as Starting and Ending time so that there weren’t any overlaps. For example, if I had datetimes for one interval from 9AM to 12PM, another from 8AM to 11AM, and a third from 5PM to 9PM, the coalesced result would be two intervals, one from 8AM to 12PM, and one from 5PM to 9PM. Basically, the point was to “simplify” a set of datetime intervals so that overlapping time would not be counted.
At first, I figured it would be built-in functionality of one of the DateTime classes. It’s not. so I did some googling, no real luck there either. So, I decided to write my own “DateRange” class that encapsulated a Start Time and an Ending time and had the functionality I required.
Obviously, the first thing we know is that the class is going to need Starting Time and Ending Time. Of course, once we’ve defined the data structures, the tricky part will be the “coalescing” code. The implementations for which can be found in the “CoalesceRanges” and “Coalesce” methods.
For this case I’ve decided that I would make the class Immutable. This should make our accessors simpler to implement. As a result, the StartTime and EndTime implementations only define get accessors. I also add a “Span” parameter that actually does change the EndTime in it’s setter, so I guess I lied. Oh well. Anyways, the meat of the class is in the various coalescing methods, which makes sense since that is what I sort of wrote the class to do. the class could surely be fleshed out with other, useful methods and properties, but as it is now it meets my own needs admirably so I’ve not really expanded it past what I’ve got here.
Anybody who has used windows is probably familiar with the ListView control. It is used in Windows Explorer; it is even used for the desktop. Heck, the ListView control even has implementations on Linux and Mac, and in the latter case it was there first.
The ListView itself can display in several modes. Normally, it shows things as Icons. But it can also be set to show Small Icons, a List, in some Operating Systems, there is a ‘Tile’ option, or even options like Large,Medium, and other sizes of Icons. My Personal favourite is the details mode.
Because I mostly see and use Listviews in Details mode, I also force people who use my software to deal with Details mode. Mostly because the reason I am displaying a ListView is to show some data in a somewhat tabular format and not just give them a few icons to drag around with minimal actual information, but I digress. Anyway, I think a good question at this point might be to look at what different parts this particular ListView has. First, the gray “buttons” at the top, which serve to title each column, are referred to affectionately as ColumnHeaders. Under each ColumnHeader there is data for a given “subitem” of each item. For example, the “Size” entry here is a Subitem for each drive. An interesting feature of columnheaders that is nearly universal is that you can click on one, and it will sort by that column.
Another interesting thing, is that in many programming environments, the ListView control doesn’t actually provide this feature for you, and you have to code it yourself. It is rather frustrating. In particular, Visual Basic 6 allows you to sort, but you can’t really customize what you sort by; it always treats it as text. In one of my VB6 applications, BCSearch (which is available for download from my Downloads page) I managed to use a Custom control, available from VBAccelerator.com, which exposes additional functionality of the ListView Control on top of that provided in either of the MS provided libraries for use within Visual Basic. One of these features is that it has better support for sorting. I still had to add my own “arrow” to show the sort direction, though.
The VBAccelerator control exposes a number of events and properties for controlling sorting, which I use to properly sort the various subitems, so that various entries like date or size aren’t sorted as text.
Curiously, the .NET Windows Forms ListView control, while having more functionality, still leaves a lot of effort to the programmer for what ideally ought to be a free feature supported by the OS. In fact it IS a free feature supported by the OS. Thankfully, the .NET control does in fact provide a feature for customizing sort functionality, And all you need is a class to implement IComparer. the IComparer will be used to compare the listitems as the Listview sorts. But if you have, say, Date and Time fields and size fields or other fields that can’t just be sorted as text, you are going to need to implement your own special comparer for each. This amounts to quite a bit of glue code; on top of that, you will need to handle the ColumnClick events on the ColumnHeader, change the sort mode, and sort it, and so forth.
To combat this bloating code, I wrote a relatively small class designed to encapsulate sorting. The idea being that you create a instance of this class for each listview, pass in the ListView to it’s constructor, and the class handles all the details. It worked quite well. There was a minor issue that amounted to a gigantic pain in the ass but at the same time made the result a lot better.
As you can see, it it relatively small (overall). the API code at the top might be a bit confusing, but it is a result of what can only be described as an oversight on Microsoft’s part; see, originally, I was changing the sort arrow header by simply changing the columnheader image. This worked, sorta of, but there was no way to remove the image and it had this weird effect where it would basically move the text and make it aligned sorta weird. Turns out that the way the ListView would “normally” show sort order icons was a built in feature of the Listview since Common Controls 6 (XP). After some SDK digging I was able to use the Platform Invoke feature of C# to call all the appropriate API functions and “force” the Listview to show the sort order in the header appropriately.
The class also exposes a custom delegate which can be implemented and passed in to the constructor, which will allow for “custom” sorts. This is useful if columns contain data like dates, or numbers that you don’t want to be sorted using the normal “text” comparison.
All in all, It’s a class I’ve added to my “toolbox”, alongside my INIFile class for accessing INI Files. did I write about that one? I forget.
Most Computer users are familiar with the Sounds that Windows emits when you plug and unplug a USB thumb drive. It’s a useful form of auditory feedback that the drive was in fact detected. However, I’ve found linux to be oddly tacit in this regard. So I set to work writing a python script that uses DBUS to monitor for new USB devices and will play a sound whenever a new Volume is attached.
As can be seen, it’s a tad messy, and even rather hackish. For one thing, it uses DBUS, which to my understanding is deprecated. Unfortunately, the replacement I couldn’t really get a clear answer on. From what I can gather, the proper method for now is libnotify and pynotify, but I couldn’t get libnotify to compile and thus was not able to properly use pynotify, and I didn’t want to have to force people to go through that sort of hell when they tried to use my script, so I stuck to DBUS.
The only limitation I discovered is that on device removal, you can’t really inspect what device was removed. At first I just figured, Just play the sound everytime and let the user figure it out, but for some reason that just assaulted me with constant device removal sounds. So I ended up commenting (and I think removing) that particular segment of code.
Playing Sounds is unnecessarily difficult in Python, or more specifically, Linux. It’s ridiculous. First I found a build in module for python, ossdevsound (or something to that effect), but attempts to use that failed because apparently it uses OSS, which apparently was replaced by ALSA for whatever reason. So I tried pygame, which errored out that I had no mixer device when I tried to initialize the mixer. So I decided to hell with it and just spawned a mplayer process, and redirected it’s stdout to NULL to avoid the nasty business where it barfs all over the console. And amazingly, that seems to work fine for device insertions, which I decided I was content with.
By default I use the Windows insertion and removal sound files. The removal sound isn’t actually used but I kept it in the g-zipped tar because I wanted to. Personally I usually just launch this in a terminal and then tuck it away on another desktop. No doubt one can execute it as a daemon or something instead and get the functionality without the console window baggage to keep around, though.

Categories
Tag Cloud
Blog RSS
Comments RSS
Last 50 Posts
Back
Back
Void « Default
Life
Earth
Wind
Water
Fire
Light 