præclarum

Search:

Frank A. Krueger
Seattle, WA, United States

Recent Posts

Finally, a thumb drive that doesn't suck
Choosing C#/Java over C++ for a beginning programm...
Dear Windows Vista
Extension Methods Make Code... Different
Why Dictionary is Great - Dynamic List with Indice...
My 1 Minute Trial of VB 2008 Beta 2
Eben Moglen
Feynman my Hero
Mr. Gore acting as Philosopher
Assimilated by Win32

Finally, a thumb drive that doesn't suck

Friday, September 07, 2007 Link

Way back in the spring, I was shopping at Fry's and decided it was time to upgrade my 16 MB thumb drive to something more... well... 21st century. So I picked up a bargain bin 1 GB drive for $20. Not the greatest bargain, but given that I once paid $400 for 4 MB of RAM, it was hardly worth debating.

I thought I was going to like it too - it had this neat mechanism that slid the USB connector to and fro - like a cheap geeky switchblade! Well, the drive worked fine, but the plastic covering and neat mechanism were complete trash. To add insult to injury, the hoop to connect to my key hoop was too small. All in all, the thing was worthless.

That is, worthless until I broke the plastic cover off and immersed it in epoxy. Now it's the greatest thumb drive I have ever owned. Check out this horrible pic:

Epoxied USB thumb drive

What is this thing you ask? Well you're seeing a semi-profile of the finished product. It's just the circuit board, the USB connector, and the electronics submerged an encased in a nice epoxy (Super Glue SY-QS complements of Home Depot).

I got the idea from some work I did for the Indian navy. We bought this ridiculously priced router that was beyond military grade - it was apocalypse grade. It will exist on this earth long after we are gone. Anyway, I digress. Upon inspection, it was just a normal router fully submerged and encased in some form of epoxy (I'm sure it was military grade epoxy).

I knew epoxy wasn't a conductor so it was worth a shot to convert my crappy Fry's drive into something useable. Well, it's now beyond useable, I actually like it a lot. It's waterproof and pretty damned rugged. So far it works just fine. I wonder how long that will last?

Now, what else can I encase in epoxy...

Choosing C#/Java over C++ for a beginning programmer

Wednesday, September 05, 2007 Link

Christopher Diggins asked me present my view on whether beginning programmers should learn C++ as their first major language. Below is the response I wrote (slightly edited).

I think Christopher's original statement "you will find yourself to be much more productive in a shorter amount of time" just about sums up my feelings towards favoring C#/Java over C++. But you must understand that the debate is more complex than the conclusion.

Christopher presented the two pro lists for the languages, but the point about automatic garbage collection in C# should be emphasized even more. As Jamie Zawinski put it (http://www.jwz.org/doc/java.html):

That one point makes me able to forgive just about anything else, no matter how egregious. Given this one point, everything else in this document fades nearly to insignificance.


I am a decent enough programmer with enough experience that most of my C++ programs have only minor memory leaks. Sometimes I can even write one without any leaks, but such ones take some patience to design. My point is that C++ makes you think about memory ownership patterns. That's something you should think about, but C++ makes you think about it so much that you don't have much brain power left to tackle other problems (like getting your program to do what it needs to do).

With Java/C#, you are freed of this burden and you can focus on the problem domain.

His list for C# is pretty good, but I would add another feature that will soon be important: declarative style queries. When I find myself writing large data-backed applications, I end up performing a lot of queries. Doing this with just Sort, BinarySearch, and Hashtables is entertaining only for so long. The query syntax of C# 3.0 allows you to enter queries against object graphs similar to what's available in SQL.

In the debate between Java/C#, I have no opinion aside from the fact that they are nearly equivalent languages. Some syntactic differences, and C# is getting a bit of a power increase in then next version, but from a language standopint they are pertty similar. Both have fantastic libraries that will let you get things done fast. Both have good communities for support. Java's one benefit is that it is
applicable to businesses who do not drink Microsoft's juice.

---

My only reservation about favoring C#/Java over C++ stems from my own growth as a programmer. I began my programming career in BASIC but quickly moved on to learning Pascal/C/C++, the classic systems programming languages, so that I could do some classical systems programming. I believe that my abilities as a programmer have been
forever tainted, ahem, I mean influenced by that early work in low-level languages (by today's standards) writing low-level code.

Once you've written a fairly large programs in these languages, everything else seems easy and enjoyable to use no matter how screwed up it is (JavaScript).

Code and data become the same thing to you. You instinctively know the memory access patterns of your applications. You do not fear pointers or any other memory construct. You can read linux kernel code with ease. You will have a desire to perform meta-programming - code generation and the like - spawned by the greatness and simultaneous weakness of C++ templates.

But, frankly, it's like forcing professors to teach elementary school for 10 years before being allowed to teach students. Sure the lessons learned are valuable, but you will learn those lessons eventually anyway.

So my advice? Grab ahold of C#/Java and don't let go. Master the languages. Then learn a new language at least once a year. If you will be working with Cat, then you are already ahead in your studies. Learn C next, then C++ later on.

Dear Windows Vista

Monday, September 03, 2007 Link

Dear Windows Vista,

You are a wretched little operating system with no redeeming attributes.

-Frank

Extension Methods Make Code... Different

Thursday, August 30, 2007 Link

Funny. When I saw extensions methods first introduced, Anders kinda treated them as hacks. They were just a little trick to make Linq compile down to standards conforming CLI assemblies.

But I like them a lot because it occurred to me that they could be used to relieve a little pain point I have when using delegates. I can't seem to conjur up the words to explain the problem succinctly, so let's just jump straight to an example.

Suppose I have a bunch of objects that have a function to query whether they are in a good state. Here's some code for that object and a little function that displays all good objects.


class Obj {
int _val;
public Obj(int val) { _val = val; }
public int Value { get { return _val; } }
public bool IsGood()
{
return (_val % 2) == 0;
}
}

void DisplayGood()
{
List<Obj> objs = new List<Obj>();
foreach (Obj obj in objs.FindAll(delegate(Obj o) { return o.IsGood(); })) {
Console.WriteLine(obj);
}
}

END

This is pretty good, but there is one part I hate. This little bit: delegate(Obj o) { return o.IsGood(); } annoys the heck out of me. I wish I could just say Obj.IsGood, but that syntax isn't supported for some reason. Hmph. This isn't a huge problem, it's just an annoyance. Especially since C# 3.0 allows me to write something like objs.FindAll(o => o.IsGood()). That's pretty good.

But for fun, I could also restructure the code to take advantage of extension methods. I could do something like:


class Obj {
int _val;
public Obj(int val) { _val = val; }
public int Value { get { return _val; } }
}
static class ObjFs {
public static bool IsGood(this Obj o)
{
return (o.Value % 2) == 0;
}
}

void DisplayGood()
{
List<Obj> objs = new List<Obj>();
foreach (Obj obj in objs.FindAll(ObjFs.IsGood)) {
Console.WriteLine(obj);
}
}

END

Hehe. I used extension methods to create a class that extends Objs with useful stuff. In this case, it's our goodness query function. Then when I want to call FindAll, I only need to pass ObjFs.IsGood.

Hmm, that was a bit work to achieve only a little. Ah well, good practice.

Why Dictionary is Great - Dynamic List with Indices

Tuesday, August 28, 2007 Link

I needed a list of objects that could be searched very quickly. I wanted to look up objects by ID, and also by property (e.g., person.City).

So I decided to write an enumerable container of objects with automatic indices. Out came the following code:


using Map = System.Collections.Generic.Dictionary<object,int>;
class Table<t> : IEnumerable<t>
{
List<t> _data;
Dictionary<string,Map> _indices;
PropertyInfo[] _pis;
public Table()
{
_data = new List<t>();
_indices = new Dictionary<string,Map>();
_pis = typeof(T).GetProperties();
foreach (PropertyInfo pi in _pis) {
_indices.Add(pi.Name, new Map());
}
}
public T Add(T value)
{
_data.Add(value);
int index = _data.Count - 1;
foreach (PropertyInfo pi in _pis) {
_indices[pi.Name][pi.GetValue(value, null)] = index;
}
return value;
}
public IEnumerator<t> GetEnumerator()
{
return _data.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public T SelectEq(string propName, object v)
{
return _data[_indices[propName][v]];
}
}


It's short and sweet (if you ignore the Blogger butchery). The idea is simple: we automatically create indexes for common queries. Those common queries are chosen to be the properties of the object.

The final magic is in the SelectEq. It takes the name of the property (as a string unfotunately) grabs the right index for that property (_indices[propName]), then grabs the index of the item whose property is equal to the queried value, then returns that item. Phew... Did you get all that?

At first, I didn't think I would be using dictionaries for the indices. I thought something like SortedDictionary would be better. I mean, indices are supposed to be b-trees, not has tables. But Dictionary drastically outperformed SortedList and SortedDictionary. But there's one small problem...

Dictionary only stores unique keys. That means that the indices require that their associated property be unique (in order for that index to work). This is fine if we only want one result. But imagine a query like table.SelectEq("LastName", "Smith"). Here we expect more than one answer. The dictionary can't help us (without making the value of the index a list). Here, the b-trees can. So I guess I need to write more performance tests to see which performs best: b-trees or dictionaries with lists.

There are more possibilities too. With only a little work, new (dynamic) indices can be created based upon a passed-in comparison predicate. That would just be wonderful.

[Update - Some more thoughts]

I don't like the fact that the SelectEq takes a string. Strings don't change when identifiers are renamed. If comparison predicates are used, then we can just pass in the delegate as the select field.

For example, let's pretend we had people and we want an index on their full name:


string SortableFullName(this IPerson p) {
return p.LastName + ", " + p.FirstName;
}


Now we can, hypothetically, create an index and begin querying:


Table<IPerson> people = ...;
people.AddIndex(SortableFullName);
people.SelectEq(SortableFullName, "Doe, John");


Yeah, that looks almost right.

My 1 Minute Trial of VB 2008 Beta 2

Monday, August 27, 2007 Link

Following my tour de force of trying WinFX for 20 minutes, I thought I would give the same treatment to the new version of VB. For reasons that are too varied to fit here, I have a special place in my heart for VB and think it's a pretty decent language (named parameters!), so I like to try it out from time to time.

VB, however, didn't get as thorough a treatment as WinFX - it pissed me off way too much within the first minute. This is too bad since I was looking forward to trying out some of its new features. (Maybe I'll come back to it when I'm more amiable.)

Also, I heard it's rude to complain about something without offering corrective action. So I decided to posts bugs for each of the problems that I will soon entertain you with.

Bug #1 lies with how annoying it is to post a bug. First you go to Help, File a Bug, then play with Micorosft's connect website. After about 6 pages of nonsense, I finally have a form where I can tell them what I think is wrong. To save you the pain, here is a direct link:

https://connect.microsoft.com/VisualStudio/feedback/CreateFeedbackForm.aspx?FeedbackFormConfigurationID=1160&FeedbackType=1

(Note to Microsoft, if you want feedback from users, make it easy for them to submit feedback.)


Now, here are the other bugs I filed:

  • Holding the control key and pressing arrows does not move the cursor. Holding control and pressing left or right should make the cursor move one "word" at a time (however VS defines "word" in this version). Instead, nothing happens. Can't believe they shipped Beta 2 with this bug.

  • Code formatter for VB automatically insists on inserting ByVal on all my params even though the documentation for VB clearly states that ByVal is the default:
"Passing Mechanism. The default mechanism for every argument is ByVal, which means the procedure cannot change the underlying variable element. However, if the element is a reference type, the procedure can modify the contents or members of the underlying object, even though it cannot replace or reassign the object itself." from http://msdn2.microsoft.com/en-us/library/cbs7z96t(VS.90).aspx.

I thought VB was a light-weight language? Why the hell then do I have to litter my code with all this ByVal noise? C# doesn't even require that.
  • Auto correction of missing subs is completely broken. So I type something like Call Foo("hello") when I still haven't defined Foo. The editor is nice enough to blue suiggle my Foo and to add an excruciatingly small outlined rectangle colored red under the last "o". Now in C# 2005, I just have to position my curso under "Foo", hit the context key on my keyboard, and choose "add stub method". VB, on the other hand, offers to create a unit test. Fine, so they screwed up the keyboard. Now if I position my cursor onto that 7x3 pixel rectangle...trying...trying...got it! Woohoow, it's expanded to something big and reminds me that I could have just hit Ctrl+Alt+F10. Thanks, that's a lot easier than just hitting the context key. Anyway, I can now easily click the big square, and, and, nothing. No corrections found. WTF? You can't even generate a stub for me? What about Ctrl+Alt+F10? Doesn't do anything. SOL I'm afraid.
And thus ended my one minute trial of VB 2008 Beta 2. My conclusion, it sucks. Oh my God, I can't even skip by word. It'll be a cold night in hell before I try to code in such a beast. When it ships again, I will give it another try. It is worth at least one minute of my time...

If you want a good development experience, just couple Resharper to VS2005. No, you don't get declarative queries, or extension methods, or literal XML. But you do get to write code. An ability that seems more and more difficult as these IDEs improve.
[Update 9:00 PM] Atleast Microsoft is fast with their initial responses. Two of the problems (the ByVal redundancy and the broken help for undeclared Subs) have been passed on to the appropriate teams. Given that Orcas is currently in it's endgame, it's possible that the issue might make it to the war team. Now the war team is responsible, essentially, for saying NO. It's their job to ship the product at a good level of quality on time. As we all know, introducing features (even options are features) at this time is generally a bad idea. Docs have to be changed, UIs changed, features implemented and tested, it's all a lot of work. Kinda late in the game to do that unless the feature is really worth it. So is removing ByVal, or fixing the Sub autogen worth it? My opinion is yes, but I can completely understand people's rejections.


Now the issue of the Ctrl word movement, the bug has been resolved pending their ability to reproduce. I guess you can't fix something unless you can analyze it. I understand. So I have two options, I can try to narrow the environmental characteristics down to the point where they can reproduce the problem, or I can just ignore it and hope it's a fluke of the machine. If I was a tester at MS and this happened on my machine, then I would be obligated to follow through with this problem. But if this is just me at home, then I'll just cross my fingers and hope for the best. Ship it.

[Update, the next day]

Looks like Microsoft threw down the hammer and has decided that both bugs won't be fixed. Guess I won't be using your language fellas. I'll catch you at version X. Perhaps you'll see the light by then.

Eben Moglen

Monday, August 20, 2007 Link

From Freeing the Mind by Eben Moglen:

Moglen's corollary to Faraday's Law says, wrap the Internet around every brain on the planet; spin the planet. Software flows in the network. It is wrong to ask, ``What is the incentive for people to create?'' It's an emergent property of connected human minds that they do create. The forms in which they create, like the evolution of spoken and written language, like the disposition of memes, cultural forms, patterns of pottery, shapes of musical endeavor, and so on, are structural characteristics of the human mind. We are a social species, and we create together; that's our nature.

Don't you just hate it when someone who represents a contrarian view to your own says something interesting, something you agree with, something that takes you aback for its eloquent statement of the greatest attribute of humanity?

Damn, and I really can't stand those GPL weenies...

Feynman my Hero

Monday, July 02, 2007 Link

There seems to be a lot of people who do not like the concept of heroes. Maybe it's a reaction against internet fanboys, but I think it's good to have someone to look up to. I have a lot of heroes in the various fields that I am interested in. Perhaps I should be calling them role-models, but I like the term Hero much more. These are the people that make our world worth sharing. Some heroes stick with you forever while others can be a bit transient. But it doesn't matter, once someone has touched your life you won't forget them. No need to burn incense or perform any silly rituals.

My heroes are of no surprise to anyone who knows me, and perhaps I'll even try enumerating my list some day. But there is no need now.

These last weeks however I was reminded of one of my heroes, Richard Feynman. I was recently re-captured by Feynman after reading QED, then by listening to his physics lectures, then by his book on the Character of Physical Law. Ealier, I really enjoyed his more playful books.

Today on Reddit I rediscovered my favorite article about Dr. Feynman. I can't do it justice by summarizing it, so instead I'll just plead with you to go read it. Please, kind reader, go read this article. I promise it is worth your time.

http://www.longnow.org/views/essays/articles/ArtFeynman.php?dupe=with_honor

Mr. Gore acting as Philosopher

Sunday, May 27, 2007 Link

I read this in a coffee shop earlier today:

To understand the final reason why the news marketplace of ideas dominated by television is so different from the one that emerged in the world dominated by the printing press, it is important to distinguish the quality of vividness experienced by television viewers from the "vividness" experienced by readers. I believe that the vividness experienced in the reading of words is automatically modulated by the constant activation of the reasoning centers of the brain that are used in the process of cocreating the representation of reality the author has intended. By contrast, the visceral vividness portrayed on television has the capacity to trigger instinctual responses similar to those triggered by reality itself--and without being modulated by logic, reason, and reflective thought.

So says Mr. Al Gore in the Introduction to his book The Assault on Reason. I am not going to comment on the rest of the book, for I have only just begun reading it, but this paragraph stuck out fiercely in my mind. In fact, it me so hard, I put down my cup of hot chocolate that I was enjoying at Victor's (I was trying to add a link to Victor's coffee in Redmond, WA but Blogger's software is so shitty that it can't even handle links that I add in using their own editor, sheesh.) and came home to post this entry.


The reason it excites me so much is that I have spent a good amount of time considering Jeff Hawkin's ideas from On Intelligence, and the research his company Numenta is pursuing. His ideas can be (poorly) summarized as follows:


  • The neo-cortex of the brain functions similarly to a Neural Network.
  • The composition of the neo-cortex is homogeneous (that is, the same "cortical algorithm" is processed in all parts of the brain in the same fashion).
  • The differences between the two lies primarily with the use of feedback in the neo-cortex (outputs from higher up nodes in the hierarchy become inputs to nodes farther down).

This view of the brain allows one to imagine how the brain is able to develop invariant forms of objects (a cat is a cat regardless of how it appears), how it can store massive amounts of information (lower nodes capture invariant representation of simpler objects, nodes higher up use those representations to develop even more complex representations, etc.)


Really, I can't do it justice here primarily because I want to get back to Mr. Gore's quote.

In the Hawkin's model of the brain, varying sensory inputs are treated homogeneously -- hearing is processed similarly to sight, sight is processed like touch, nervous reactions (pain) are again processed similarly. Imagine the brain as one huge neural network that's constantly consuming input (of any kind!) and that is constantly driving outputs (feedback to lower neurons, drive currents for muscles).

This model of the brain explains a lot, but conscious thought is still something that is very difficult to subjugate to the cortical algorithm. Perhaps it's my desire that there is more to being human than simply containing an over-grown neo-cortex. I don't know, but I feel that there is more to me than a simple state machine.

Enter Al Gore's argument. He was in the process of exposing the reader to the fact that the American population has become numb to government and (perhaps rightly) politics. Part of his argument rests in the reader believing his point that television is a one-way medium and that we have become robots digesting our programming.

Given Hawkin's theory of cortical algorithm amplifies Mr. Gore's thesis. If our brain is just one big neural network -- feedback or not -- it will adapt to its sensory input. I will become emotionally attached to Peter's plight against Sylar, and I will wonder what exactly the Cylons intend to do next...

But there is this annoying consciousness of mine. The one that keeps nagging at me saying things like "people can't fly", "given a design capability beyond what we have today, super-intelligent robots would not re-create themselves in our image", "a Gundam's cockpit would place too much strain on the pilot", "Cheney looks creepy", "those angry people with the swords and guns don't seem to be getting any less angry".

It seems to me that Al Gore is stating that reading the written word naturally invokes this aspect of our brains while TV keeps us happy in the cortical algorithm.

God, I hope you were able to make sense of any of that. I apologize for the side topic, it just seemed interesting to me. Stay tuned for more programming-related fun. To keep this site balanced, I'll even throw in some pointer-arithmetic in the next post.

Assimilated by Win32

Sunday, May 27, 2007 Link

This is a repost of an article I wrote back in March 2006. It seems to have fallen through the cracks as I moved from my own software to Blogger. Here it is for your enjoyment.


I always regarded straight Win32 development (that is, GUI app development using no wrappers over the Win32 API) as too time-consuming and tedious. Because of this, I have taught myself the big six: MFC, ATL, WTL, VCL, WinForms, and WPF (not at all in that order).

Nowadays I find myself using WinForms a lot. Even when not using the interactive designer of Visual Studio, WinForms makes a lot of GUI development trivial. However, there is a price you have to pay in order to use WinForms and the WPF; that price is managed code.


Now I love managed code. It provides a safe execution environment, a million classes that do two-million things (referring to the .NET library), garbage collection, excellent multi-language interoperability, and a very simple machine against which to write compilers. Let me repeat, I love managed code. But that’s not what this article is about.

Sometimes I feel the need or am forced to write unmanaged code. Even worse, sometimes I feel the need or am forced to write unmanaged GUI code. When it comes to native GUI code, I have a choice between MFC, ATL, WTL, VCL, or straight Win32. Prior to a month ago Win32 wasn’t even an option. It’s too ugly, it’s too old-school (where are my classes?), and nobody does it. Well, those were my opinions.

This last year, I have spent way too much time reading through all of The Old New Thing, Mark Russinovich’s Sysinternals Blog, Joel on Software, and Larry Osterman’s Blog (among others). These guys are old-school to be sure.

Old-school, in this instance, means not using C++’s (or C#’s, or Java’s, or Eiffel’s) object-oriented style of programming. You know the type: information hiding, single-object virtual function dispatch, lots of smart pointer, RAII, horrible function composition through bind, blah, blah, blah. No, instead, they tend to utilize more imperative function-based approaches. This is the style of coding that makes the source code of Project Oberon, and Quake (I, II, and III), and MMIXware, and the Linux Kernel, and SICP (and SICM), such a pleasure to read. They are devoid of the noise of modern object-oriented-programming languages, and contain nearly pure signal. This is also the style of the Win32 API.

Anyway, the point is that I have been thinking a lot about increasing the signal-to-noise ratio of my own code. I began to consider whether I could meet such an end by coding straight to the Win32 API. So I embarked on an experiment to write an application using straight Win32 and to compare that experience with writing WinForms apps.

I’ll summarize my conclusion: I like Win32 development. The Win32 API isn’t nearly as bad as I once thought, and some parts of it even scream out “I was designed very well!” This is not the conclusion I expected. I expected to get 1/4 of the way through development and to abandon the idea as just another waste of time.

So I was wrong, and I even look forward to the next time I get to write a native Win32 application. This article describes what I found along the way and the style of code that I eventually adopted that made development a breeze.


Let’s Begin with WinMain.


Open Visual Studio, create a new Win32 Project (without MFC or ATL) and you will get 8 files with the main C++ file consuming nearly 200 lines of code. Not
a great start at all. This is a part of the intimidation of Win32 projects. If it takes 200 lines and 8 files of overhead to create the base application, then how large is the Win32 overhead of the real application going to be?


As it turns out, not much overhead at all. These 200 lines, while foreign and a bit clumsy looking, aren’t bad at all. There are four functions generated for you (ignore the silly About function). These are WinMain, MyRegisterClass, WndProc, and InitInstance.


The first function WinMain is your entry point and the controller of the main GUI thread of your application. It is responsible for registering your window classes (more on those in just a moment), for creating the main (top-level) windows of the application, and for dispatching the messages for those windows. That’s just about all that your WinMain should do, and that’s all that the generated WinMain does do. There are of course some other trivial matters to accomplish such as initializing various services (Winsock, COM, CommonControls, etc.) but we only need to add that as necessary.


Object-oriented Windows.


So what about this registering window classes stuff? As it turns out, and this is the largest mental block to get through when first developing Win32 applications,
the windows API is object-oriented. That is, it has a notion of classes and instances. Every window on the screen has a class and that class dictates the behavior of that window and, often times, its child windows.


The class of the window, specifically, defines a few superficial traits: icons, cursors, and default background brushes, some esoteric traits: class styles, and “extra” information, and the most important trait: what to do when the window receives messages.


If we think about the Win32 notion of windows in terms of the C# object-oriented model, then the API defines an abstract Window class has one abstract method: HandleMessage. When you wish to create a new window class, you simply need to define a new class that overrides this function. To summarize in code, the OS would define the abstract window as:



class Window {
public virtual Result HandleMessage(Message msg) {
// Default processing of msg
}
}

The application developer would then define their own windows as:

class MyWindow : Window {
public override Result HandleMessage(Message msg) {
// Special processing of msg
}
}

The Win32 API is nearly identical to this setup with the only restriction that new window classes can only derive from Window and none of its (derived) base classes. Of course, the Win32 syntax is quite different too. Instead of the class definition of MyWindow above, one would instead write:

ATOM RegisterMyWindowClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex = { 0 };
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpfnWndProc = MyWindow_HandleMessage;
wcex.hInstance = hInstance;
wcex.lpszClassName = L"MyWindow";
return RegisterClassEx(&wcex);
}

Here, the function MyWindow HandleMessage overrides the default message handler (DefWindowProc) of the window. The registration process is a bit more verbose than the C# definition, but they are equivalent. Also, I should note that this is an incomplete registration, some important field assignments to wcex have been neglected to keep parity with the C# sample. Both the Win32 procedure and the C# class definition would have to be expanded to include all the options that
Win32 allows for window classes.

In C#, one would create a window by instantiating an object of the appropriate type (class). That would look something like:


Window wnd = new MyWindow(...);

In the Win32 world, window creation is just as simple:

HWND hWnd = CreateWindow(L"MyWindow", ...);

Again, I’m simplifying things, but the point is clear: the Win32 system is a class based system with one polymorphic function, the WndProc.

Once a window is created, the HandleMessage (or WndProc) function is responsible for defining the behavior of that window. Behavior here includes how the window responds to the user, how it responds to the OS, and how it displays itself.

It does all of this using the simple and robust method of message passing. When you want to tell a window to do something, you send it a message telling it what to do. When you want to get some information, you send it a message asking for information. When the window needs to tell other windows what to do (usually child windows), it sends them messages.

In the C# WinForms world, you add a bunch of public methods to a window class and invoke those methods in order to accomplish the same tasks. Message passing and function invocation are two means to the same end. Again we see the roots of OOP in the Win32 API.

In fact, the authors of SICP uses message passing to implement an object-oriented system. Since the Scheme programming language is quite a bit more powerful than the C programming language (against which the Win32 API has been designed), the Win32 message system isn’t nearly as rich as the SICP system; however, the ideas are the same. (Message passing can also be used to implement a very robust form of data sharing and control in concurrent applications. The programming language Erlang makes excellent use of this mechanism.)

Let’s take a step away from all these generalities now and answer the important question: how can I use the Win32 API to create rich applications with minimal effort.

My idea is to go with the flow. If the Win32 API is based around window classes and messagepassing, then let’s make full use of those ideas. Our assumption is that if we simply allow ourselves to be assimilated by the API, then we should find no resistance to using it and application development will become easier.


Assimilated Win32 Development.


The first step to coding a GUI application is to determine what classes of windows are needed. If I was writing a text editor, I may choose to create a new
window class that is superior to the built-in Edit and RichEdit classes of Windows. I could then use this “SuperEdit” wherever the user needed to enter data. If I was writing a simulation package, then I would develop a “WorldView” window class that could display some physical manifestation of the objects I was simulating. If I was writing a strip-chart viewer (think heart monitor, or seismograph, or lie detector), then I would create a class of window tailored to displaying strip-charts.

These are the types of things that the VCL refers to as components, and what WinForms refers to as controls. Me? I’ll just call them windows.

The first order of business for creating a new window class is to write the RegisterXClass function, where X is the class name of the window. This will be very similar to the one shown above. Refer to the documentation of WNDCLASSEX to learn of all the wonderful options you get.

Next, we need to implement some WndProc for that window. This function can begin simple and be added to as more functionality is required of the window. So we begin with a simple one:



LRESULT CALLBACK X_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
default: return DefWindowProc(hWnd, msg, wParam, lParam);
}
}

We have now defined a window that does nothing more than emulate the default window. It accomplishes this by deferring all responses to the default WndProc. In order for the window to do something more interesting, we need to handle more messages.

As I mentioned briefly before, the Windows message system isn’t very rich. In fact, messages only carry three bits (not literally) of information: the message type, and two parameters, wParam and lParam. Because of this limitation, the true contents of a message are encoded into those two parameters. For instance, if you need to pass a complicated structure as a part of the message, then you can pass a pointer to that structure as one of the parameters. Windows makes use of this
and many, many more techniques for passing data with messages. For this reason, nearly every message has its own unique encoding based upon its type.

This is one of those things that at first makes Win32 coding seem so tedious. You end up spending a lot of time in MSDN figuring out just what the exact encoding of each message really is.

This must have gotten really old really fast for the Windows developer’s too since they ship a header file with the SDK that simplifies this whole process. The header file windowsx.h contains a macro for each of the pre-defined windows messages. This macro automatically decodes the parameters and invokes an event handler for each message. This makes writing the WndProc a breeze and leaves the developer only with the challenge of coding the logic of the handlers.

Let’s look at an example use of these macros. We know that we will need to override keyboard input to the window since a window that doesn’t react to the user is usually pretty annoying. To override the key input, we can handle the WM_KEYDOWN message.

Open windowsx.h and search for WM_KEYDOWN. There, we see a comment and a macro
definition:



/* void Cls_OnKey(HWND hwnd, UINT vk, BOOL fDown, int cRepeat, UINT flags) */
#define HANDLE_WM_KEYDOWN(hwnd, wParam, lParam, fn) \
...


The first commented line is a prototype of a function to handle the message. The second line begins a macro that will call that function from our WndProc.


We copy that prototype and paste into our own code to create our event handler:



static void X_OnKeyDown(HWND hwnd, UINT vk, BOOL fDown, int cRepeat, UINT flags)
{
...
}

This function will contain any process that should be taken whenever the user presses or hold a key down. Within switch statement of the WndProc for the window, we also have to add this simple line:



HANDLE_MSG(hWnd, WM_KEYDOWN, X_OnKeyDown);


The macro HANDLE_MSG will be sure to invoke the macro HANDLE WM KEYDOWN and
that macro will call our X OnKeyDown function. All messages will have a similar invocation of the HANDLE_MSG macro.


You should continue to repeat this process for each of the messages you wish to handle. Doing so will result in a very clean and simple WndProc and a set of event handlers that exactly match the messages you wish to handle.


Window State.


A window usually has some state associated with it. Text boxes must remember
their text; strip-charts must have access to the data to display; etc. Given the method for implementing a window class given in the previous section, we are never given a chance to record our state. (And let’s not even contemplate the idea of storing the state as a bunch of global variables. If we did that, then we would only be able to instantiate one instance of our window class. This defeats the whole purpose of using classes in the first place.)


Because we need the state of the window to be attached to each instance of a window, and because instances of a window are represented by HWNDs, we had better associate our state with the HWND. Fortunately, there is a very easy way to do this. All windows have a pointer-sized amount of memory in which the user (here, the programmer) can place anything they want. The function SetWindowLongPtr allows us to write to that pointer-sized area, and GetWindowLongPtr allows us to retrieve the value there.


Let us then create a single struct that contains all of the state of our window. When the window is created, we will allocate and initialize this data and store a pointer to it using SetWindowLongPtr. Then, whenever we need access to our state, we can use GetWindowLongPtr to retrieve it.



Here is a complete example of a window (well, minus the registration function) that implements such a scheme for storing its state.



struct X_State {
int c;
};
template
BOOL CreateAndSaveState(HWND hWnd)
{
BOOL fSuccess = FALSE;
T *pt = (T*)calloc(1, sizeof(T));
assert(pt);
if (NULL != pt) {
SetLastError(0);
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pt);
if (0 == GetLastError())
fSuccess = TRUE;
else
free(pt);
}
return fSuccess;
}
static BOOL X_OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)
{
return CreateAndSaveState(hWnd);
}
static void X_OnDestroy(HWND hWnd)
{
free((X_State*)GetWindowLongPtr(hWnd, GWLP_USERDATA));
}
LRESULT CALLBACK X_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
HANDLE_MSG(hWnd, WM_CREATE, X_OnCreate);
HANDLE_MSG(hWnd, WM_DESTROY, X_OnDestroy);
default: return DefWindowProc(hWnd, message, wParam, lParam);
}
}

In this example, we have a window with a single integer as its state. It creates and remembers this state when it is created by handling the WM CREATE message. I have given a complete version of the handler for that message, X OnCreate. This handler is robust in the sense that if there is any problem recording the state of the window, then the creation of the window is terminated all together. When the window is destroyed, the state is also destroyed.


Because the OnCreate handlers for all our windows will be pretty similar (they only differ in the type of state), I utilize a template function that handles the nitty gritty of creating and storing away the state. Please keep in mind that this template is only valid for plain old data (POD) structs and classes; that is, for structs and classes that do not have constructors, destructors, virtual functions, or contain classes with constructors, destructors, or virtual functions. If you wish
to make it a little more C++ friendly, then the calls to calloc and free should be replaced with new and delete. I preferred to use calloc and free simply because I wanted a guarantee that the code would not throw an exception. Exceptions are great in functional code, but really create disasters in imperative code.


Also, don’t forget that you’ll probably want to put a call to PostQuitMessage in the OnDestroy handler of your main window. If you do not do this then your application process will keep chugging along with no visible windows! That is not very user-friendly thing to do.


Commanding through Messages.


We have dealt with the definition of a window’s class and its
storage of state. Only one element remains: the control of the window by code. Up until now, our window operated solely on its own; to make it function cohesively with the rest of the application, we have to have a way to communicate with it. Again, we use messages to communicate with windows.

We can define our own message types for communication with our window. These messages mirror member functions of classes. We can have message for setting and retrieving state, and we can have messages that force the window to perform more complex operations. In the case of the strip-chart, we may define a message such as SC PAUSE that causes the display to stop updating with new data. In the case of the world view simulation window, we may define a message such as WV_ZOOM in order to zoom in and out.


Defining new messages is easy. We simply create a constant (either through a macro or a C++ const declaration) for the message type. The only stipulation that Windows places on these new messages is that their ordinal value should be no less than WM_USER.


So we could go ahead and state things such as:



#define SC_PAUSE (WM_USER+1)
#define WV_ZOOM (WM_USER+2)


And, with that, we have created new messages.


Our lives only become a little more complex when we decide to associate some data with the messages. We need to encode that data into the two parameters wParam and lParam. Life is simplest if we just bottle up the data into a struct and pass a pointer to that struct as the lParam. A lot of the Win32 functions do this, and it is pretty simple.


We must only force ourselves to make our own lives easier by writing HANDLE_* macros,
similar to those found in windowsx.h, for our own messages. This way our WndProc will have one uniform structure that is easy to interrogate and maintain.


We can also make the lives of the user of our window easier by implementing simple wrapper macros around SendMessage. Windowsx.h does this for the standard controls (see for example Edit GetLineCount amongst others) and it is a real time saver. Essentially these wrapper macros are defining a functional interface over the message passing system. We get the best of both worlds!


Putting it all Together.


Now that we have defined exactly what functions and macros we need
to create for our window classes, let’s talk briefly about code organization.


Under the principle of encapsulation, I try to put as much code as I can in its own translation unit (cpp file) and declare the functions as static so that they cannot be mistakenly called.


This means that each window class will have its own translation unit. In that unit, all functions (except one) will be marked as static. The WndProc will be static along with all the functions it calls. The one exception to this rule is the class registration function. This must necessarily be visible to the application code so that it can be called at initialization time. A prototype of the function will also be given in a header file for the window.


The message constants and macros of the previous section will also need to be contained in this header file. And that is it. The public header should be short and sweet: the register function, and the message macros. The state struct should not be in the header. That should exist only in the translation unit.


Following these rules creates a situation where all windows’ data are safely tucked away, and the clients of these windows have simple and strict means of interfacing with them.


Conclusion.


This article details my best understanding of the path of least resistance when
developing Windows GUI programs. In the past I have tried a variety of class libraries to make GUI development easier. What I have realized over time is that these libraries usually don’t make anything easier and typically reduce the signal to noise ratio of my own code. With that in mind, I have set a few simple rules to follow when developing these applications. When these rules are followed, I find Win32 development to be a simple and enjoyable.