Tuesday, September 30, 2008

eComics, MRU's and My Recent Documents

Well, my testbed for WindowsForms development has received another release. Version 0.0.1.003 of eComic is now up, and waiting for downloading over at Codeplex (http://www.codeplex.com/ecomic/).

Quite a number of changes for this release, most of them are fixing behaviors, getting things closer to creating/using a reading list, but there were two that I really wanted to point out. These two are new classes that I added into my source code; one is a MRU Files listing, and the other adds accessed files to the "My Recent Documents" list on the user's START menu.

The latter of the two is merely a simple WIN32 Interop wrapper for the SHELL DLL. Nothing obscenely fancy, but it works.

The former (see the source code here) is a bit more involved. It's a class, which takes in 3 things: a ToolStripMenuItem object, the application's name and the number of files that can be on the MRU list. It then generates additional ToolStripMenuItems to go into the intial ToolStripMenuItem's DropDownItems attributes.

The class itself raises an event when one of those child Menu Items are chosen, passing the selected file path & name to the parent class. I just shoved this information into the registry because that was easy for me, but it wouldn't be that hard to retrofit it to store the data into a database or even a flat file.

Friday, September 26, 2008

eComically Funny

Yes, I'm stretching with that title. But hey, I've got fun things in store for myself. Anyways, I'm almost ready to release the next alpha version of my freeware program eComic. This little bitty release is primarily to fix the ability to read the archive files when the images are contained in subfolders (recursion FTW!).

I've also pushed out more functionality on the ImageViewer screen, which will allow the user to load a random archive from that screen, and save the currently visible image to the file system.

I've also gotten rid of the ClickOnce installer and went with a more traditional MSI file. I don't know why but I just don't like that ClickOnce paradigm. It bothers me for some reason or other.

Thursday, September 18, 2008

CBR, CBZ and maybe something new

I can admit, I'm having fun with eComic. But that's neither here nor there. Currently, I support opening CBR and CBZ files, which are fundamentally RAR and ZIP files respectively. For the record, CDisplay, the initial program that dealt with these things had 4 file formats: CBR, CBZ, CBT, CBA, which corresponded to RAR, ZIP, TAR and ACE files.

The thing that makes a CB# file a CB# file, is that it is filled with images, and possibly a "Notes.txt" file. It's not a complicated file paradigm--which I do like.

Now, making them is relatively easy. You stick all the files you want in the CB# in a folder, and then zip or rar or tar or ace it up. Rename the file extension and you got yourself a file.

Bad news is that you've GOT to have them name in something sequential. Much the same way that the CB# file itself needs to be named sequentially in order for CDisplay to find the next thing to be read.

So, my thought was to have eComic create a new file type. Let's call it GNZ. Now the GNZ will fundamentally be a CBR file. Except the Notes.txt will be replaced with a Manifest.xml file.

The Manifest.xml file will have something along the lines for a schema:

Note two things of interest for the new file type:
  1. The images are given an order that they should be displayed in
  2. The note information is stored, and give a format (types can be RTF, HTML or TEXT)
... maybe I'm just too pleased with myself.

Wednesday, September 17, 2008

Codeplexing for Fun

And if only this were for profit as well..

Anyways, this past weekend, I had some spare time on my hands. And what better way to fill that spare time than to purchase lots and lots of SF/Geek memorabilia.

But, since I don't have enough money to do all of that, I decided to just wrote some code instead.

The thing is, I coupled two reasons to code into a single project.

The first reason is that I was wanting to use the ZIP libraries in .NET in a WindowsForms environment. I know I'll be dealing with them soon professionally, so I wanted to figure out how to use them, and get that out of the way.

The second thing is that I have an application I use called CDisplay, which is a sequential image viewer, which I want to extend the functionality for. Basically, I want to be able to create a "Reading List" which allows me to pick and choose which archives I want to view, and the order I want to view them in.

Why? Well, I use this to read comics. I'm a geek, it's allowed. Now, if I wanted to read say the "Fatal Attractions" crossover from the late '90's X-Men, then I'd have to read the following comics in this order:

  1. X-Factor (Volume 1) #92
  2. X-Force (Volume 1) #25
  3. Uncanny X-Men #304
  4. X-Men (Volume 2) #25
  5. Wolverine (Volume 2) #75
  6. Excalibur (Volume 1) #71
Now, if I've scanned every issue of my comic collection into my PC, and followed a wise naming convention, then the the disparate archive files would be called:
  1. xfactor_v01_0092
  2. xforce_v01_0025
  3. uncannyxmen_v01_0304
  4. xmen_v02_0025
  5. wolverine_v02_0075
  6. excaliber_v01_0071
The problem here is that these guys are NOT sequential. When I would open xfactor_v01_0092, the next logical file would be xfactor_v01_0093 not xforce_v01_0025. The xforce_v01_0025 is only the next logical file in the context of the "Fatal Attractions" storyline.

Hence the need for a reading list for this thing.

So, there you have it. I'm in the process of building this little application because, well, I'm crazy that way, and feel the need to ramble on about it here on this blog while doing so.

Without further ado, here's my codeplex site: http://www.codeplex.com/ecomic

Saturday, September 13, 2008

And A Great Big Modified Dietz To You Too

I don't work well in the heat. Especially when it's a heat without airflow. Sure, the office was only 82 degrees F, but without a fan or anything, I was just flat-out miserable and all I wanted to do was curl up somewhere and gaze at a wall or something. Heck, I seriously considered going out to the truck, and getting my gym bag to trade my work clothes for my work-out clothes, all in an effort to keep my brain from overheating.

Or in Bender parlance, I was just shy of closing my eyes, and when I re-opened them stating "Insert Girder."

Now, why is this important? And more importantly, why am I bringing my issues with heat up on my programming blog? Well, outside of the fact that the heat thing happened at work, this heat thing slapped me down while I was trying to uncover the secrets of using four different algorithms.

Sure, they all calculate the same types of data, but they do it in highly divergent ways.

What algorithms you ask? Well, they're financial ones, specifically those related to calculating Investment Performance. The four in question are: Internal Rate of Return, Daily Valuation, Modified Dietz and Modified BAI (sometimes called Modified IRR).

Now, these things are evil. They're geometric algorithms, as they deal with compounding data sets over time, with sums and subtractions in addition to, and conjunction with the compounding data.

Don't believe me? Then look at this:
Or how about this:

Yes, those are two of the formulas I'm turning into a calculator. And doing it while my brain is frying like one of those proverbial eggs.

Hmm, now if only I had some bacon.

Alas, thanks to our good friends at Wikipedia, at least some of the Modified Dietz things have been dealt with. Their article provides this VB source code for calculating Modified Dietz:

'Jelle-Jeroen Lamkamp 10 Jan 2008
Dim i As Integer: Dim Cash() As Double: Dim Days() As Integer
Dim Cell As Range: Dim SumCash As Double: Dim TempSum As Double

'Some error trapping
If rCash.Cells.Count <> rDays.Cells.Count Then MDIETZ = CVErr(xlErrValue): Exit Function
If Application.WorksheetFunction.Max(rDays) > iPeriod Then MDIETZ = CVErr(xlErrValue): Exit Function

ReDim Cash(rCash.Cells.Count - 1)
ReDim Days(rDays.Cells.Count - 1)

i = 0
For Each Cell In rCash
Cash(i) = Cell.Value: i = i + 1
Next Cell

i = 0
For Each Cell In rDays
Days(i) = Cell.Value: i = i + 1
Next Cell

SumCash = Application.WorksheetFunction.Sum(rCash)

TempSum = 0
For i = 0 To (rCash.Cells.Count - 1)
TempSum = TempSum + (((iPeriod - Days(i)) / iPeriod) * Cash(i))
Next i
MDIETZ = (dEndValue - dStartValue - SumCash) / (dStartValue + TempSum)
Thanks Wiki!!


Wednesday, September 3, 2008

Installing and Launching Applications

So, one of my myriad projects I have going on is a run-once and forget about it application which modifies the resolution order for Outlook Address books (fun stuff, I know). Forget the fact that this is evil MAPI and C++ stuff (made even eviler via Vista), and also deals with the arcane Outlook COM objects in C#, I got it working.

After a number of hours of smacking my head against the wall, I got it working.

Well, as a final bit, the client requested that it install and then run and that's all it needs to do.

My initial thought was, let's just drop it into the START folder under the program list, and have it run every time the system reboots. The client didn't want this, as all he wanted was a run once and never have to bother with again type of thing.

Well, Aaron Stebner has a solution which actives that "Run this application" checkbox in the MSI system, which can be found here.

Which was almost what I wanted. The problem there is that I want to FORCE the application to run EVERY TIME it is installed.

Which led me to this CodeProject article: Launching your application after install using Visual Studio 2005. Outside of the circular reference to my first link, and the fact that the title is slightly misleading, this does exactly what I want.

Which is launch the application AFTER the install, but prior to the INSTALLATION wizard finishing.

Which makes me happy, the client happy, and the world just that much of a better place for everyone involved.

Good times.

Monday, September 1, 2008

SQL Membership Provider

I love the .NET Login controls. They're the easiest things in the world to use--provided you're happy with the arcane and more or less evil Membership tables that are generated by aspnet_regsql routine.

And of course, I'm not.

I often want little things like using the email address as the username. Everyone knows their email address, and in ensures that I collect that information (yes, I'm sneaky).

Usually this means many hours of arcane coding while I implement my own versions of the Membership and Roles providers, when ultimately all I want to be doing is modifying things every so slightly.

This is a concept that makes me ecstatically happy once I found that the source code for the SQL Membership Providers have been released by Microsoft (a fact discovered via Scott Guthrie's blog in this post).

Sometimes I'm so behind the curve.

Blog Widget by LinkWithin