Short version: open registry, look for file association entry, locate the command subkey and check if, besides the (Default) value, there isn't a command multistring value that looks garbled. Rename or remove it.

Now for the long version. I've had this problem for a long time now: trying to open an Office doc file by double clicking it or selecting "Open" from the context menu or even trying "Open with" and selecting WinWord.exe threw an error that read like this: This action is only valid for installed products. This was strange, as I had Office 2007 installed and I could open Word just fine and open a document from within; it only had problems with the open command.

As I am rarely using Office at home, I didn't deem it necessary to solve the problem, but this morning I've decided that it is a matter of pride to make it work. After all, I have an IT blog and readers look up to me for technical advice. Both of them. So away I go to try to solve the problem.

The above error message is so looked up that it came up in Google autocomplete, but the circumstances and possible solutions are so varied that it didn't help much. I did find an article that explained how Office actually opens up documents. It said to go in the registry and look in the HKEY_CLASSES_ROOT\Word.Document.12\shell\Open\command subkey. There should be a command line that looks like "C:\Program Files\Microsoft Office\Office12\WINWORD.EXE" /n /dde. The /dde flag is an internal undocumented flag that tells Windows to use the Dynamic Data Exchange server to communicate the command line arguments to Word, via the next key in the registry: HKEY_CLASSES_ROOT\Word.Document.12\shell\Open\ddeexec which looks like: [REM _DDE_Direct][FileOpen("%1")]. So in other words (pun not intended) WinWord should open up with the /n flag, which instructs to start with no document open, then execute the FileOpen command with the file provided. If I had this as the value of the command registry key, it should work.

Ok, opened up the registry editor (if you don't know what that is or how to use it, it is my recommendation to NOT use it. instead ask a friend who knows what to do. You've been warned!), went to where the going is good and found the command subkey. It held a (Default) value that looked like it should and then it held another value named also command, only this one was not a string (REG_SZ), but a multi string (REG_MULTI_SZ), and its value was something like C84DVn-}f(YR]eAR6.jiWORDFiles>L&rfUmW.cG.e%fI4G}jd /n /dde. Do not worry, there is nothing wrong with your monitor, I control the horizontal, vertical and diagonal, it looked just as weird as you see it. At first I thought it was some weird check mechanism, some partial hash or weird encoding method used in that weird REG_MULTI_SZ type, which at the moment I didn't know what it meant. Did I mention it was weird? Well, it turns out that a multi string key is a list of strings, not a single line string, so there was no reason for the weirdness at all. You can see that it was expecting a list of strings because when you modify the key it presents you with a multiline textbox, not a singleline one.

So, thank you for reading thus far, the solution was: remove all the annoying command values (NOT the command subkeys) leaving the (Default) to its normal state. I do not know what garbled the registry, but what happened is that Windows was trying to execute the strange string and, obviously, failed. The obscure error message was basically saying that it didn't find the file or command you were trying to execute and has nothing to do with Office per se.

Of course,you have to repeat the procedure for all the file types that are affected, like RTF, for example.

I am the kind of guy that uses a piece of software until he has a really good reason to change it. I don't try new stuff if I am satisfied with what I've got and I am all for second chances when mistakes are made. After all, I am not immune to the occasional error. However, from this day on I am fully switching from Internet Explorer to Chrome.

Wipe that smirk off your face, I happen to think that IE is a reasonable browser and, given the hypothetical situation where Google would have made their browser compatible with Internet Explorer rather than the standards, you would all curse at FireFox right now. Besides, this is not about the standards at all. Firefox is still not on my list of available choices. It is sluggish, pretentious and buggy.

The thing is that parameters have changed. I now use the browser to quickly get answers to questions or to open RSS feed blog articles. Before I was using it to make ASP.Net applications and web applications and I still think Internet Explorer 8 developer tools are nicer and easier to use than Firebug, not to mention the horrible confusing developer tools on Chrome. Now I am free (partially) of web development and I can rejoice. Also, sites were more compatible with IE than any "standard" browser and it is not the case any more.

The downloading window from Internet Explorer always made more sense to me: have an option of Open, Save and Cancel and do it in another process so you can close the windows that spawned the download. Then it opens or you just go to the file and use it, you know where you saved it. I think this is the only thing I will miss from Internet Explorer, though.

Let's summarise:
  • Chrome opens instantly, letting you write something in the address bar immediately and having autocomplete for search term as well as web addresses. Internet Explorer blocks the CPU for a second or two and, even if it lets you write something in the address bar, it hickups just so that what you wrote is truncated. Firefox is so keen to update every fucking extension that it takes forever to start. Yeah, I know, FF4 is way better. Not compared to Chrome it isn't.
  • Internet Explorer is supposed to support the new Silverlight wonder technology. Unfortunately, every single SL video I open is sluggish, blocks my mouse, doesn't respond to simple commands like Space to pause and arrows to skip and every Silverlight app is alower than their Flash counterpart. I've just wasted one hour today to uninstall with a special tool the older Silverlight version as the installer for the new one brutally stopped with a "generic error message". Well, screw that! I would rather download the videos and run them in a "generic" video player
  • Javascript: it works 8 times faster on Chrome that on Internet Explorer 8. I know they've just released Internet Explorer 9, but it won't work on Windows XP. I have an old computer, it works fine, I want a browser for it without buying a trillion dollar Windows 7 license. You can't provide it for me, Microsoft!
  • HTML5: it is supported in Chrome. If I ever want to start web dev again, I would go with that
  • Extensions: I am not a big fan of extensions as they slow the browser down. I do prioritize speed. However, I have AdBlock Plus installed on Chrome and I couldn't install it (even if I have tried emulating it) on Internet Explorer. Having no flashing nonsense on a page when I am reading the text on it is wonderful. Try it!


I could find even more reasons if I think about it longer. Like a long relationship going bad, you start noticing all the things you hated only after you break up, but break it up I do. So there it is, found me a new girlfriend and she is chrome shiny.

As you know, the uberuseful tool Reflector, originally developed by Lutz Roeder, was bought by Red Gate, with promises that the tool will always remain free for its users. Of course, the first thing they did is to create a commercial version of it with some extra features, but they did keep their word by allowing people to use a free version. Recently they changed their minds again, practically saying "Fuck you, developers!" and asking for money for any version of Reflector. The community was outraged.

Enter Jetbrains, my favourite company, the one that would have replaced Google and Microsoft at the top of the development world if they weren't so busy actually developing. They are also the makers of ReSharper, which you should download and use if you are any decent C# programmer. What did they think of this Reflector fiasco? They've decided to build a version of their own! They did bundle it in ReSharper 6, which is a commercial tool, but then... they promised to make it a free standalone tool! Thumbs up, guys!

Here is the blog entry announcing this: ReSharper 6 Bundles Decompiler, Free Standalone Tool to Follow

Update: in order to execute a script in any open tab inside Chrome, use the executeScript method of the tabs API.

Chrome browser extensions are so cool, that they protect you from accidentally running and adding script to a page that might interfere with the original code of the page. Unfortunately, they don't give you a parameter or option to actually do that, if it is what you actually want. All you can do, by default, is to access the elements in the page document, but not change direct members of window or even document.

I have found the solution on this page: Writing a Google Chrome extension: How to access the global context of the embedding page through a content script.. There is code and explanations for the code, but basically it is a function that injects another function in the real page context and also returns a result.

A while ago I wrote a post detailing how to install Windows XP on a laptop with SATA drivers without using any floppy disk. Today I had to do such installation again and I've met with some annoying errors.

The laptop was an Acer Aspire, so I did everything in my old post and started the computer. It is important to use the correct drivers, as in my case the installation met with a blue screen with code 0x0000007B. It was like it tried to use some of the SATA drivers I had loaded on my WindowsXP CD, but not the right ones.

After the installation went ok, Windows XP would not boot up, not even in safe mode. In order to check what the hell is going on (because the default behaviour is to show a blue screen and immediately reboot) you need to start the computer and press F8, then disable the automated restart in case of error from the menu.

The problem is that the laptop had "AHCI mode" enabled in BIOS. Apparently, Windows XP doesn't support this mode. Set it to IDE BEFORE you start installing Windows XP. After that, you can enable AHCI after you install some stuff and change some registry entries, but it seems XP doesn't really have much use of this mode of access anyway. Here is a forum discussing this, but I haven't got around to trying the things described there yet.

Good luck with your installation. I almost went for installing Windows 7. Phew!

Today a power outage screwed something in my Visual Studio installation. For the life of me I couldn't figure out what went wrong and I also didn't have the time to properly investigate. The issue appeared when I restarted the computer, ran Visual Studio 2010, loaded a project (any project) and tried to compile. Invariably, an error would prevent me from building the project:Error 22 A problem occurred while trying to set the "Sources" parameter for the IDE's in-process compiler. Error creating instance of managed object 'Microsoft.VisualStudio.CSharp.Services.Language.Features.EditAndContinue.EncState' (Error code is 0x80131604). Application.

I have tried disabling Edit and Continue, I've tried to disable the Exception Assistant and also I've re-registered the dlls in the Visual Studio 10.0/Common7/IDE folder, all to no avail. Even worse, it seemed as I am the only person on Google (yay!) that got this error so I couldn't find a quick no effort solution (boo!). The error code 0x80131604 stands for HRESULT COR_E_TARGETINVOCATION, or a TargetInvocationException, which is thrown by methods invoked through reflection. So that is that.

The solution was to reinstall Visual Studio. It took half a day, but it fixed it. If you have met the same issue and you found a quicker way, please leave a comment.

I have been waiting for this game for 12 years, just like everybody else, but not for the usual reasons. I like the Blizzard stories. I liked the Starcraft tales of the first game and I absolutely loved the Warcraft III plot. I was expecting something glorious this time. Well... I was kind of disappointed. The story is pretty linear, with cowboy characters and dialogues seemingly stolen directly from the propaganda in Starship Troopers.

But first, a word from our sponsors :). The campaign has a secret mission. Read about it before starting the single player game. So even if you have a Queen of Blades nagging you talking a walk around the base and buying her Xel'Naga artifacts, don't rush the Media Blitz mission. ;)

I have this old Sempron 2500+ with 1Gb of RAM. The game, at the lowest possible settings, was snail paced. One needs memory for this baby. I am not blaming Blizzard for my laziness in buying a computer, but it seemed to me that all the slowness came from reasons that could have been addressed. For example the game (as it should) remembers correctly every keystroke and mouse click in battle. However, in the HUD or in the game menu, one has to wait for the buttons to light up before clicking, and then keep pressing until the button lights up the second time. In game, the greatest slowness came from special effects that were not related to the game play. I understand a suspended nuke over a flowing lava fountain might exert the CPU of a computer, but the animation itself could have been scaled down to an animated GIF for crying out loud. The cinematic animations were pretty nice, and I loved how when I ran out of resources the film would not freeze, instead the characters would wait for the next part of the dialogue, breathing and moving their eyes. But still, since there is no interaction whatsoever from the user, can't you precache it into a movie? One that can be played on any computer and has the video in sync with the audio?
So yes, the game is running slow on my computer, but I feel that it could have worked a lot better with only some minor tweaks of the in game interface.

The in game interface is pretty nice, completely 3D and the map itself is 3D and some units (a precious few) can take advantage of that, like hopping jet packed soldiers or air-ground transforming machines called the Vikings). However, the game play is almost identical to the first game, so the 3D feels kind of pointless. There are camera zoom and rotation abilities, but the zoom out is limited to a pretty low setting and the zoom in is kind of pointless unless you have female units to properly look at :)

The units of the game are interesting enough. The old units have been morphed, replaced, removed, and new units were added. For the humans are multiple types of turrets, including machineguns on the bunkers, air units dropping turrets and a special mind control tower that permanently captures zerg units. The Goliaths are still there, but also a more heavy, ground focused Thor unit is available. There are multiple soldier units other than the Marines and Firebats, like hopping and grenade launching units. It is funny though, most human soldiers and vehicles are focused on attacking only ground units. The air units have been reinvented. There are small troop carriers that can heal units, really big Hercules troop carriers, the Battlecruisers have an upgrade that allows them to attack air units with missiles, the Valkirie is gone, but it was replaced by the Viking, a sort of transformer unit that can fly and attack air units or transform into a walking robot that attacks ground units. There are two types of science vessels and they repair mechanical units instead of firing EMP pulses. There are two types of ghosts, too.

The Zerg have been transformed, too, as well as the Protoss, but I can't really address this issue until I play some multiplayer games to see it from all perspectives. And yes, I guess you already know by now, but I will tell you anyway: after 12 years of waiting, you only get the human campaign. The Zerg follows, then the Protoss, probably in expansions to the game.

There is a mini campaign with the protoss, where any two templars (dark or light) can be morphed into an Archon, but I have seen no trace of the Dark Achon. I really loved that unit. I hope they didn't remove it. Also the zerg overlords need to transform into Overseers in order to be observers; they lose the ability to transport and to pour creep from the air (yeah, really cool) and instead have the ability to spawn banelings, creatures that attack ground units and transform into the same low level unit they encounter, like a zealot or marine or something like that. I know this because, while missing the Dark Archon, I really loved the human zerg capturing beacon tower :) I haven't seen any lurkers, either. I liked them, too. Instead there are some walking buildings that burrow in the creep and become normal ground turrets. Maybe that's the only way to build ground turrets now.

There were some real innovations to the game. The units that can hop to high ground is one of them. The way SCVs are repairing nearby structures and mechanical units without someone having to tell them to do it is something that I really liked. Also you can place a building over ground covered by your own units and they will just move out of the way. You also get useful alerts, like idle SCVs. I liked that as well. There is a special human building where one can call mercenaries, specialized unit squadrons that have extra health and deal extra damage. Also, in the story, there are research points that you earn and use them to select one of two choices in a list of pairs of technologies. For example you can choose to slow zerg units instead of capturing them with the beacon, you can choose stronger bunkers instead of machine gun equipped, etc.

That being said, there are still ridiculous ways in which groups of units interact. You can't easily tell a group of medics to accompany and repair a marine unit. If you select them all and attack, the medics will heal the marines, but if you tell them to move, they won't! If you select multiple air and ground units, there is no way to tell them to clump together. The air units will just go over and die, while the ground units use the scenic route. Units do move out of the way of other moving units, but only for a while, sometimes getting into infinite loops. As in the previous game, the forward line of an attack group doesn't know to move a little forward to let the back like be in attack range and heavily hit units don't really have any way to retreat while others are covering.

So yes, I guess one can enjoy the game as the one before, but I am the kind of guy who likes automatic transmission, cars that park themselves and, hopefully in the near future, drive themselves. I would have created an entire option panel that described how units ought to behave.

Now for the story. Spoilers alert! If you want to play the game and see the story unfold, stop reading!.

The sector is mostly occupied by humans. Mengsk has overthrown the government and became emperor, one that is even more brutal and oppressive than the one before. In the process he betrayed his partners: Jim Raynor and Sarah Kerrigan. Raynor is now the leader of the resistance, while Sarah Kerrigan was abducted by the Zerg, transformed into an infested version of herself and has since taken over as the leader of the Zerg, after the Protoss have destroyed the Overmind.

So Raynor is doing mischief trying to get to Mengsk, while the Zerg appear in the sector and start taking over human worlds. The Protoss couldn't care less. They occasionally purge worlds of Zerg (by destroying the entire planet, inhabited or not) or hold up in sacred locations, bent on stopping anyone from taking their precious holy artifacts.

You see, the Protoss are believers in the Xel'Naga, their creator gods. Well, what do you know? The Xel'Naga actually exist, they created the Protoss and the Zerg and now they are returning. Looking like hybrids of Protoss and Zerg, they have shields, they can heal really fast and can corrupt zerg units into becoming their slaves. Probably tired of waiting 12 years to get the second Starcraft game, they are pretty pissed and want to corrupt all the Zerg into destroying all life in the sector, then commanding them to kill themselves, thus ending all life.

Raynor is here to save the world so, with a little premonitory help from his friends Zeratul and Tassadar, he sees what the Xel'Naga plan and sees that the entire future depends on him NOT KILLING Kerrigan. She alone can do something against the Xel'Naga. We also learn that the Overmind was under the control of the Xel'Naga all the time and it created the Queen of Blades from Kerrigan as a solution to its enslavement, thus proving great courage. Poor Overmind :'(

Therefore, the purpose of this campaign is to get to the Queen of Blades and use an ancient Xel'Naga artifact to purge the Zerg out of her. Badly enough, Infested Kerrigan is not the sexy babe she was in the first franchise, instead she is some afro-mongoloid with bad skin and shiny eyes, so I was highly motivated to see her brought back to normal.

The story has three choice points, which can slightly alter the plotline. One is when the world where you relocated some humans you saved gets infested. Protoss units come to purge the world and you can have the choice of purging the world yourself or fighting the Protoss to stop them. Later on, one can choose whether to use Ghosts or Specters. Specters are a slightly insane version of the Ghost created by one of Mengsk's secret programs. Then, on Charr, you can choose to destroy the Zerg Nydus worms or their air units. I was also mentioning a secret mission, found if destroying a conspicuous building in the Media Blitz mission.

Obviously, I purged the humans and kept the spectres. I killed the Nydus worms, too, but I think that's clearly the more sensible solution when you have the capture beacons.

!!! Uberspoilers !!!

The campaign ends with Raynor untransforming Kerrigan, killing Tychus who has been sent to kill her, probably by some Xel'Naga influenced human group (I dare say it would have been stupid for Mengsk to ally with the Xel'Naga, but he is a likely culprit) and purging Charr of all Zerg.

Ok, there are also some cheats that can help you end the game faster. You won't get any achievements if you use them, but then again, you need to play the uncracked version to use achievements, so the hell with them.

Update February 2016:If you just want to disable R#, like it is not installed, go to Tools → Options → ReSharper → Suspend/Resume

I've been using ReSharper (R#) for a long time now and I can tell you that if you are a Visual Studio C# developer and you are not using it, you are missing out. These guys must have the greatest job in the world: develop for developers. Or could it be the worst job, since doctors always make the worst patients? anyway...

I have been preaching about ReSharper for about 4 years now and the most common complaint from people new to it is that it makes things go slowly in certain situations. The thing is, R# is doing so much stuff in the background, that I find it amazing it moves so fast as it does. It is a valid complaint to want to have the same speed of typing and moving around that you have in the normal Visual Studio environment and still have the many features provided by ReSharper.

So, my solution was to have a command to "pause" the ReSharper analysis until I need it. The scenario would be:
  • Suspend analysis and regain swiftness of typing
  • Write your fingers off, since you already know what to type and even Intellisense feels like slowing you down
  • Resume the analysis and get all the R# goodness
In other words, something like writing your code in notepad and then copy pasting it all in the VS window.

Well, as most of the time, the R# have thought about it already! You have two possible options. One is using the commands ReSharper_Suspend, ReSharper_Resume and ReSharper_ToggleSuspended. You can either bind them in the Tools -> Options -> Environment -> Keyboard to whatever combination you desire, or go to Tools -> Options -> ReSharper -> General and use the Suspend button. This is equivalent to enabling/disabling the ReSharper addon. Since it is a very large addon and needs a lot of resources and hooks, this option is terribly slow. It does have the advantage of freeing all memory used by R#. The second option is more what I was having in mind: the command ReSharper_EnableDaemon. It sounds kind of like "Release the Kraken!" and it works in a similar way. What it does is suspend/enable code analysis on the current file! It is already bound as a global shortcut on Ctrl-Alt-Shift-8. It works almost instantly and enables the scenario I wanted.

Bottom line: Ctrl-Alt-Shift-8 to suspend/resume code analysis on the current file so you can type like your livelyhood depends on it. Again, thank you, JetBrains!

Update: It seems on older versions of ReSharper (not 5), the shortcut is Ctrl-8.

First of all, check the WindowsUpdate.log file found in the Windows folder. It should tell you how the update failed. Look for something looking like this: WARNING: Command line install completed. Return code = 0x0000066a, Result = Failed and later on WARNING: Install failed, error = 0x80070643 / 0x0000066A.

If you have the same error, check this article out: Fix KB974417 Installation Failure—Microsoft .NET Framework 2.0 Service Pack 2 Security Update for Windows 2000, Windows Server 2003, and Windows XP.

However, my problem was that I had NOT installed the KB976569 Windows update that the guy recommends removing before installing the new one.

I found this article: KB 953297 and KB974417 Fails to Update Through Windows Update that recommends a clean reinstall of the .NET Framework. Haven't tried it, though. I just didn't do the update. Probably when all hell breaks loose I am going to regret it, but at least I passed the message on :)

I have been using Internet Explorer as my main browser since IE 3.0 and usually I have no problem with it. I know the rendering engine is a piece of crap, but I got used to the feel of it and the developer tools in IE8 are nice and FireFox just rubbed me the wrong way, so that was that.

But since Internet Explorer 7 upwards, and especially with IE8, the first loading of the browser got slower and slower. So slow, in fact, that I have to wait several seconds for the browser to allow me to use the address bar. No wonder I have been slowly using Chrome for searching and reading the news and all that.

Today I got kind of annoyed with it and started looking into the Internet Explorer options. An advanced one was Enable third-party browser extensions and I removed it, just to see what it would do. Suddenly I had no Google toolbar (but I don't use it anyway, since I enter all my searches in the address bar), Flash worked, the pages worked, the internal IE8 developer tools worked. The only difference is that Internet Explorer would load instantly!

Ok, that would work as a last option, but I got intrigued so I enabled the option again and went into the Manage Add-ons section. I haven't being paying attention before, but each add-on in the list also has displayed the loading time. I looked around and I found Groove GFS Browser Helper that loaded in ... 8.2 seconds! Disabled it: almost instant browser loading. Two other addons had over one second load time, both of them from Sun and related to Java (which almost no one uses anymore in web pages). Disabled them and now I have my browser back! Just for the sake of it I googled for Java Applet and went to a site with a Java on it. Amazingly, the applets all worked! So the addons themselves were not responsible for loading Java, they were just useless junk.

But what is this Groove thing? Is it some malignant Microsoft rival that purposefully makes its browser addon load slower as to sabotage Internet Explorer (hint! hint!). It appears not. As it usually happens, the greatest enemy of Microsoft is Microsoft itself: Groove comes from Microsoft Office 2007!

What does Groove Syncronization do? Microsoft Office Groove was designed for document collaboration in teams with members who are regularly off-line or who do not share the same network security clearance. In other words: nothing useful. Even better, the whole groovy thing can be easily uninstalled, which I also did.

To uninstall Groove go to Add or Remove Programs, look for the Microsoft Office entry, click on Change, remove Groove. That's it!

Happy New Year! May the year bring... wait a minute, I didn't mean to add to the noise that follows any large celebration like the New Year. In fact, quite the opposite. I intend to show you a way to block the outside noise in a relaxing way while on your computer.

Many a time a simple mp3 player would do the trick, however, sometimes you need to read boring documentation and that makes your brain switch to the text of the songs played rather than stay focused on what must be read and understood. Enter SimplyNoise, a simple site that generates white, pink and brown sound, with an optional feature to modulate the volume, thus shielding you from the outside audio interference, yet not disttracting your attention.

This also helps with tinnitus, if you have the misfortune of suffering from it. Recent research also shows that the condition can be alleviated if the specific frequency of the tinnitus sound is blocked. If they would block some frequencies from their generated sound, they would actually provide a medical service.

My personal favourite is the brown sound with modulated volume. Sounds just like standing on a beach.

Happy relaxed coding!

Yay! New Github project: EasyReplace.

What it does is replace all files in a folder hierarchy with the files you drag&drop on the app info box. It is very helpful when you want to replace old library files or some other versions of your files with newer ones without having to manually navigate through solution folders.

For a few weeks I have been having problems running Silverlight on my machine, especially since I had SL3 installed and also Expression Blend, version 3. I didn't mind much, because I don't need Silverlight most of the time. But since sometimes I do, here is the solution for the "Your Silverlight developer components are out of date" error when trying to install Silverlight.

Go to http://go.microsoft.com/?linkid=9394666 and install the Silverlight tools. Yes, they are version 2. No, I don't know why Silverlight 3 would have problems because of version 2 Silverlight tools. However, installing the tools solved my problem.


Today I've released version 1.2 of the HotBabe.NET application. It is a program that stays in the traybar, showing a transparent picture, originally of a woman, sitting on top of your other applications. Clicks go through the image and the opacity of the picture is set so that it doesn't bother the use of the computer. When the CPU use or the memory use or other custom measurements change, the image changes as well. The original would show a girl getting naked as the use of CPU went up. Since I couldn't use what images it should use, I did my own program in .NET. This blog post is about what I have learned about Windows Forms while creating this application.

Step 1: Making the form transparent



Making a Windows Form transparent is not as simple as setting the background transparent. It needs to have:
  • FormBorderStyle = FormBorderStyle.None
  • AllowTransparency = true
  • TransparencyKey = BackColor
However, when changing the Opacity of the form, I noticed that the background color would start showing! The solution for this is to set the BackColor to Color.White, as White is not affected by opacity when set as TransparencyKey, for some reason.

Step 2: Making the form stay on top all other windows



That is relatively easy. Set TopMost = true. You have to set it to true the first time, during load, otherwise you won't be able to set it later on. I don't know why, it just happened.

Update: I noticed that, even when TopMost was set, the image would vanish beneath other windows. I've doubled the property with setting WS_EX_TopMost on the params ExStyle (see step 4).

Step 3: Show the application icon in the traybar and hide the taskbar



Hiding the taskbar is as easy as ShowInTaskbar = false and putting a notification icon in the traybar is simple as well:
_icon = new NotifyIcon(new Container())
{
Visible = true
};
Set the ContextMenu to _icon and you have a tray icon with a menu. There is a catch, though. A NotifyIcon control needs an Icon, an image of a certain format. My solution was, instead of bundling an icon especially for this, to convert the main girl image into an icon, so I used this code.

Step 4: Hide the application from Alt-Tab, make it not get focus and make it so that the mouse clicks through



In order to do that, something must be done at the PInvoke level, in other words, using unsafe system libraries. At first I found out that I need to change a flag value which can be read and written to using GetWindowLong and SetWindowLong from user32.dll. I needed to set the window style with the following attributes:
WS_EX_Layered (Windows Xp/2000+ layered window)
WS_EX_Transparent (Allows the windows to be transparent to the mouse)
WS_EX_ToolWindow (declares the window as a tool window, therefore it does not appear in the Alt-Tab application list)
WS_EX_NoActivate (Windows 2000/XP: A top-level window created with this style does not become the foreground window when the user clicks it).

Then I found out that Form has a virtual method called CreateParams giving me access to the style flag value. Here is the complete code:
protected override CreateParams CreateParams
{
get
{
CreateParams ws = base.CreateParams;

if (ClickThrough)
{
ws.ExStyle |= UnsafeNativeMethods.WS_EX_Layered;
ws.ExStyle |= UnsafeNativeMethods.WS_EX_Transparent;
}
// do not show in Alt-tab
ws.ExStyle |= UnsafeNativeMethods.WS_EX_ToolWindow;
// do not make foreground window
ws.ExStyle |= UnsafeNativeMethods.WS_EX_NoActivate;
return ws;
}
}


However, the problem was that if I changed ClickThrough, it didn't seem to do anything. It was set once and that was it. I noticed that changing Opacity would also set the click through style, so I Reflector-ed the System.Windows.Forms.dll and looked in the source of Opacity. Something called UpdateStyles was used (This method calls the CreateParams method to get the styles to apply) so I used it.

Update: Apparently, the no activate behaviour can also be set by overriding ShowWithoutActivation and returning true. I've set it, too, just to be sure.

Step 5: Now that the form is transparent and has no border or control box, I can't move the window around. I need to make it draggable from anywhere



There is no escape from native methods this time:
private void mainMouseDown(object sender, MouseEventArgs e)
{
// Draggable from anywhere
if (e.Button == MouseButtons.Left)
{
UnsafeNativeMethods.ReleaseCapture();
UnsafeNativeMethods.SendMessage(Handle,
UnsafeNativeMethods.WM_NCLBUTTONDOWN,
UnsafeNativeMethods.HT_CAPTION, 0);
}
}
Both ReleaseCapture and SendMessage are user32.dll functions. What this mouse down event handler does is say to the Window that no matter where it was clicked, it actually clicked the draggable area.

Step 6: Remove flicker



Well, I am getting a bit ahead of myself, here, the flickering becomes annoying only when I implement the blending of an image into another, but since it is also a style setting, I am putting it here:
SetStyle(ControlStyles.AllPaintingInWmPaint 
| ControlStyles.UserPaint
| ControlStyles.OptimizedDoubleBuffer, true);
This piece of code, placed in the Form constructor, tells the form to use a double buffer for drawing and to not clear the form before drawing something else.

Update: It seems the same thing can be achieved by setting the Control property DoubleBuffer to true as it seems to be setting ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint and ControlStyles.UserPaint seems to be set by default.

Step 7: Blend the images one into the other



Well, in order to make an image blend nicely into the next, I used a Timer. 10 times a second I would decrease the opacity of the first, increase the opacity of the second and draw them one over the other.

A small detour: if you think about it, this is not absolutely correct. A 70% opacity pixel blocks 70% of the light and lets 30% of the image behind show. If the image underneath has 30% opacity, then it shows 30% left from 30% of the image and it doesn't get opaque. But if I just set the opacity of the bakground image to 100%, it shows really strong on the parts of the images that are not overlapping, where image1 is transparent and image2 is not.

Unfortunately there is no resource friendly way to read write/pixels. It's either GetPixel/SetPixel in a Bitmap class (which are very slow) or using pinvoke again. I prefered to use the opacity hack which looks ok.

I was already using an extension method to invoke any change on the form on its own thread (as the Timer ran on its own thread and I would have gotten the "Cross-thread operation not valid: Control [...] accessed from a thread other than the thread it was created on" exception or "Invoke or BeginInvoke cannot be called on a control until the window handle has been created"):
public static void SafeInvoke(this Control control, Action action)
{
if (control.IsDisposed)
{
return;
}
if (!control.IsHandleCreated)
{
try
{
action();
}
catch (InvalidOperationException ex)
{
}
return;
}
if (control.InvokeRequired)
{
control.BeginInvoke(action);
}
else
{
action();
}
}

This is where I got the "Object is currently in use elsewhere" InvalidOperationException. Apparently the Image class is not thread-safe, so both the timer and the form were trying to access it. I tried locking the setter and getter of the Image property on the class responsible with the image blending effect, with no real effect. Strangely enough, the only solution was to Clone the image when I move it around. I am still looking for a solution that makes sense!

Step 8: Showing the window while dragging it



Using WS_EX_NOACTIVATE was great, but there is a minor inconvenience when trying to move the form around. Not only that the image is not shown while moving the form (On my computer it is set to not show the window contents while dragging it), but the rectangular hint that normally shows is not displayed either. The only way to know where your image ended up was to release the mouse button.

It appears that fixing this is not so easy as it seems. One needs to override WndProc and handle the WM_MOVING message. While handling it, a manual redraw of the form must be initiated via the user32.dll SetWindowPos method.

The nice part is that in this method you can actually specify how you want the form draw. I have chosen SWP_NoActivate, SWP_ShowWindow and SWP_NoSendChanging as flags, where NoActivate is similar with the exstyle flag, ShowWindow shows the entire form (not only the rectangle hint) and NoSendChanging seems to improve the movement smoothness.

Quirky enough, if I start the application without Click through set, then the rectangle hint DOES appear while dragging the window. And with my fix, both the image and the rectangle are shown, but not at the same time. It is a funny effect I don't know how to fix and I thought it was strange enough to not bother me: the rectangle is trying to keep up with the hot babe and never catches on :)

Step 9: Dragging custom images



I am a programmer, that means that it is likely to add too many features in my creations and never make any money out of them. That's why I've decided to add a new feature to HotBabe.NET: droppping your own images on it to display over your applications.

At first I have solved this via ExStyle, where a flag tells Windows the form accepts files dragged over it. A WndProc override handling the WM_DROPFILES message would do the rest. But then I've learned that Windows Forms have their own mechanism for handling file drops.

Here are the steps. First set AllowDrop to true. Then handle the DragEnter and DragDrop events. In my implementation I am checking that only one file is being dropped and that the file itself can be converted into an image BEFORE I display the mouse cursor hint telling the user a drop is allowed. That pretty much makes the ugly MessageBox that I was showing in the previous implementation unnecessary.

Step 10: Reading files from web, FTP, network, zip files, everywhere, with a single API



Reading and writing files is easy when working with local files, using System.IO classes, but when you want to expand to other sources, like web images or files bundles in archives, you get stuck. Luckily there is a general API for reading files using URI syntax in the System.Net.WebRequest class. Here is a sample code for reading any file that can be represented as an URI:
WebRequest req = WebRequest.Create(uriString);
using (var resp = req.GetResponse())
{
using(var stream= resp.GetResponseStream())
{
// do something with stream
}
}


WebRequest can also register your own classes for specific schemas, others than http, ftp, file, etc. I created my own handler for "zip:" URIs and now I can use the same code to read files, web resources of zipped files.

One point that needs clarification is that at first I wanted an URI of the format "zip://archive/file" and I got stuck when the host part of the URI, mainly the archive name, would not accept spaces in it. Instead use this format "schema:///whatever" (three slashes). This is a valid URI in any situation, as the host is empty and does not need to be validated in any way.

The rest are details and you can download the source of HotBabe.NET and see the exact implementation. Please let me know what you think and of any improvement you can imagine.

I've stumbled upon this Windows port of a Linux application called HotBabe. What it does is show a transparent image of a girl over your applications that looks more naked as the CPU is used more. I wanted to use my own pictures and explore some of the concepts of desktop programming that are still a bit new to me, so I rewrote it from scratch.

The project is now up on Github and is functional. Please report any bugs or write any feature requests here or on the project page in order to make this even cooler.

Features:
  • Custom images responding to custom measurements
  • Custom measures (included are Cpu, Memory and Random, but an abstract class for custom monitor classes is included)
  • AutoRun, ClickThrough, Opacity control
  • Interface for custom images and custom monitors
  • XML config file


Update: After adding a lot of new features, I've also written a blog entry about the highlights from HotBabe.NET's development, a "making of", if you will. You can find it here: Things I've learned from HotBabe.NET.

Enjoy!