Work in progress, screenshots and sketches
Shadow copying is in, for those pesky locked Outlook mailboxes and other "in use" files.

There are three big things left to weave into the program - file system monitoring, new delta copier and software updates - and the beta is good to go. A matter of few days now.
If your message box includes the "Don't ask again" option, just make sure to disable all but one button, when it checked.

Oddly enough, I don't know a single app that does that.
On light | On dark
A system tray icon sprite sheet.

Feeling creative? Make your own version, save as a PNG, drop it in a config directory and - voilà - your systray looks just like you want it to.
There are two sets of icons on the sprite sheet. The first three columns is the XP style, which is a bit puffy and matches well older Windows styling. The last three columns is a flat version that goes better with native W7 tray icon style.

Each icon comes in 3 sizes - 16x16, 20x20, 24x24. This is needed to accommodate 3 common DPI levels, see this earlier entry for details.
Final | 2-framer | Shaker 1 | Shaker 2
"Message pending" indication, whereby a message can be either an error, a warning or a notice and these are differentiated with the ! color.
I realize it's not color-blind friendly, but the goal is to attract the attention and make user bring the app window up to read the message --(therefore)--> reflecting the message type via an icon level is not exactly critical.
W7-ish version as per a this hint on Twitter. Not bad at all.
Working on systray icons...
Revised Preferences window a bit.

Added basic control over backup scheduling and switched from "close to systray" to "minimize to systray" - the (x) at the top right corner will now always act as an Exit, just as it is supposed to.
More of the UI work.

Custom pop-out button that stays nice, flat and out of the way when idle, but acts like a regular button otherwise. Not exactly a UI innovation, but it was nice to be able to use it in a real project :)
Option 1 | Option 1/b | Option 2 | Option 2/b
Took out the engine mode switch from the Preferences and into a dialog of its own. Still need to understand if it's worth mentioning that there's an engine per se or just stick to more amorphous "application mode"...
Option A | Option B | Option C | Option D
Looked at few options for splitter styling. First one is final. Tentatively though... heh.
Done with the split-view mode for the main window. It's one of those things that everyone takes for granted and that, in reality, maps to quite a bit of work if done right.

For example, resizing window by the top edge should resize the top pane and leave the bottom part alone.

Likewise, resizing by the bottom edge should expand/compress the bottom pane, but not the top one.

However, if we are compressing window by the top edge and the top pane is at its minimal height, then we should the bottom pane starting to compress.


All good so far, but, say, we change our mind and start expanding the window back (without releasing the mouse button).

We should see the bottom pane brought back to its original size first, followed by the expansion of the top part... even though we are, technically, dragging by the top edge.


This sort of UX detail is something that few people will notice if it's done right, because it feels natural and aligns well with expected behavior. But cut some corners - and you bet everyone will notice.
Option A | Option B | Option C | Option D
Going through styling options for the expand/collapse buttons.

Presently leaning towards C or D, because I'm considering making the text selectable with the mouse for easy copy- pasting. For that to work the buttons need to be as unobtrusive as possible.

Still WiP though...
Working on the backup log viewer.


Basically the idea for the log is to support multiple detail levels, each capturing progressively more context that its parent.

With all details collapsed, the log gives a quick overview of when the job was running and if it completed OK or with errors.

Expanding details allows for a drill-down - to look at the details such as the file and byte counts, the timing and performance data and the details of any errors that have occured.

I'm still going to shuffle things around the window, e.g. push the -/+ buttons to the right, tweak the styling too, but the general hierarchical format will stay. It is a very convenient way of organizing the log info.
Finished a piece of code that determines effective timestamp resolution of a file system.


Every file system keeps track of when a file was created and when it was last modified. These timestamps are the natural properties of a file and they are readily available for inspection in the Windows Explorer or any file manager of your choice.

The less obvious aspect of timestamping is that timestamps have resolution. For example, FAT tracks file modification with a measly 2 second precision. In comparison, NTFS uses the 100 ns (nano-second) precision.

It is very typical for a backup software to rely on timestamps to determine if a file has been modified and requires copying. But if the source file sits on an NTFS volume and the backup goes onto a FAT disk, then comparing timestamp directly simply won't work, because FAT timestamp will be rounded-up to a 2-second mark.

In other words, the timestamp granularity needs to be taken into an account when comparing the timestamps. The question is how to determine what it is exactly.

First of all, the granularity for creation and modification times can be different. FAT has them at 10 ms and 2 s respectively, but NTFS has them both at 100 ns.

To complicate matters, there appears to be NAS devices that look like NTFS boxes, but with the granularity that is not 100 ns.

So what I did is added code to probe the file system and determine effective resolution for both timestamps. This involves dropping a temporary file and then trying to set its timestamps to this, that and 3rd and see what they end up at. From that it's possible to deduce the resolution.

In cases when such probing fails, the app falls back to guessing resolution by the file system name. It is also possible to override the resolution values from the config, just in case.
Done with the backup scheduler. Comes with a couple of neat improvements over v1.

The Go and Stop buttons work almost exactly as in v1. If the backup is running, click Stop once to Pause it, click again to Cancel, click third time to disable the job. If the job is disabled, click once to enable it, click again to manually start it. And so on, you get the idea.


First improvement over v1 are the Go! and Stop! commands that are activated by holding Ctrl down when clicking on the toolbar buttons.

Go! moves the job straight into the running state.
It's the "Run it. NOW!" command.

Stop! stops and disables the job straight away.
It's the "Stop it. NOW!" command.


Second improvement is that multiple jobs can now be run in parallel. Generally, this has a negative impact on the overall performance, but there are certain cases when this is desirable. One example would be running a smaller backup in parallel with a much larger and slower one.

There are three ways to do this:

  • With the Go! command.
  • With a per-backup setting that makes the job always run right away, even if there's another job is running.
  • With an app-level setting that does the same, but for all jobs.

PS. I considered adding something more elaborate, e.g. allowing assigning jobs to "run groups" and then allowing only one active job per group, but that seemed like an overkill, so I dropped that.
Another pass over the main window chrome and layout. The "backup jobs" section is just a dummy header ... and it is confusing, I think.

† This is an app screenshot, not a sketch.
Terse | Two-liner | Four-liner
Exploring options for the main window format.


Specifically, I want to get rid of the V1's Summary panel, trim the information contained in it a bit and fold it directly into the main window items.

In conjunction with this I'm also considering having two modes for displaying backup jobs on the list - "terse" one-liners and "extended" multi-liners. What I still need to figure out if this should be a per-item preference or an app-wide setting and how one would switch between these display modes.

Work in progress, obviously. Any thoughts - let me know.
Done with a little animation that and switches main window between a "welcome screen" and the regular backup list view.

The animation and fading effects can be disabled, there's a setting for that.

Windows comes with a standard toolbar control, but it's an overkill if you need just a couple of buttons at the top of the window.

It basically takes longer to figure out how to use and customize it compared to creating a basic window and sticking a couple of custom buttons on it.

Had I have a need for toolbar ribbons, docking, on-the-fly customization, etc., then ToolbarWindow32 makes sense. But if it's something simple, then there are faster options.
Meet the toolbar.

To explain a bit what you see in this masterpiece :) -

The idea is to try and keep the menu/toolbar area simple and flat, but still provide some sort of a visual clue that Go and Start are clickables.

Here are three options compared back to back to make the differences a bit more obvious -


Here are few options that were leading up to the above one:









iOS says Hi




Also, considered disposing off the menu bar and folding whatever few items it has into the drop-down menu. But this just looks weird and too alien on Windows, the app needs a menu bar.

Dropped the idea.
Option A | Option B
The look of the main window with no backups configured. Tried using a stock button, but it looks heavy and dull. Hopefully, this is a bit more refined.
Shorter | Iconic | Longer A | Longer B
Trying to understand how to indicate if a selected path points at a removable storage.

The app tracks storage devices being plugged into the computer and it adjusts backup paths if a known device re-appears under a different drive name.

I can, of course, not bother with this at all and simply spit out a notification when (and if) the drive change is detected, but then I think it's an important functionality and it'd better be mentioned during the setup.
"Work-in-progress" buttons for beta releases.
Correct your input.

† Idea is courtesy of the OS X login screen, I think. Though I did experiment with concise error indication quite a bit.
Wrapping up the Periodic Backup configuration window.

Unlike the v1 that always stored the backup interval as a number of seconds, the v2 adds a time unit specifier.

This simplifies quite a few things in the UI and yet it keeps the configuration flexible enough to support 1.5 hour backups by allowing to specify a 90 minute interval.

On an unrelated note, killed few hours trying to utilize native Windows controls for the interval configuration. The amount of work required to make them look reasonably good is as depressing as it is remarkable.

For example, the editbox control doesn't natively support vertically centering the input text. It just does not. It is meant to look like this -

Want "120" aligned to the label on the left? Sure thing, that'd be 2 hours of plowing through documentation only to realize that it must be... drum-roll... a multiline control that you will then need to manually pad the right amount at the top to push the line to the middle.


But that's peanuts compared to trying to beat some sense into the dropdown box. Long story, but making a box taller and keeping the line centered requires taking over the control drawing functions, which in presence of Windows themes is a delightfully unpleasant experience.

In any case, turning the top control line into the bottom one -

costs exactly a day of work, while it really shouldn't. Welcome to Windows.
Finalized the design of inline hint/tip widget for input controls.

Initially, it was meant for the config window that hosts periodic backup settings (as seen in a couple of posts below), but having talked to others and slept on the issue I think that the natural language input (i.e. requiring to enter "1 week" or "15 minutes") is not the best option for this case.

An alternative design is coming up in a bit.
Coded the previous sketch, played with few parameters and it is starting to get there ... I think. Will make another pass over this tomorrow and it should be good to go.
For what it's worth I have also gave a try to the standard Tooltip Control. In fact, that's where I started.


A regular tooltip looks like this -

It adds another layer to the windows stack, breaks the visual flow of the layout and still manages to tuck itself under the mouse cursor.

There's also a balloon version of the same, which looks like this -

It is marginally better, but just look at those lovely rounded cornersi. Eat that Apple. Real artists ship.


tl;dr - the standard Tooltip Control is not very good, so I had to come up with a custom replacement.
Not sure about this one, seems a bit clumsy and a bit too custom.

This is basically a way to explain what is expected as an input for a particular configuration value. There's gotta be a cleaner way of delivering the same info...
Compact form | Fully expanded
Working through the supporting code for the Settings window.

Done with collapsing/expanding mechanics and respective fading and moving animations. Still need to revise the copy for the explanatory bits and massage in the option for archiving deleted files.


Not to pat myself on the back, but I think it came out looking pretty decent.

That's not to say there's no way to turn off all this fancy styling and animations, because, you bet your favourite monochrome flat design, there is.
The Backup Settings window. Final ...for now :)
Revision 2.a | 2.b | 2.c | 2.d
Another take on Backup Settings window, 4 styling variations.

Further compacted vertically, but now it appears to be somewhat cluttered and lacking comfortable vertical rhythm (to borrow a term from the typography).
Basic | Overview | Expanded section
Working on the Backup Settings window.
I think the original design from the version 1 got many things right.

It provided a good at-a-glance overview of the backup configuration, split settings logically and tucked away the minute details. It did have one problem - it was tall. So tall, in fact, that I got several reports that it didn't fit on screen :-|


V2 adds several new options to the backup config, so this doesn't make things any easier. After looking at few options, including paged, tabbed and two-column, screenful layouts, I circled back to the v1 layout.

To compress it vertically I've done two things - got rid of the group boxes (frames) and collapsed radio button groups into a single line with the current selection.

This gives us the middle screenshot (pic) that shows the config window in the "overview" state.


Clicking on a "Change ↓" button expands the radio button group and allows changing the setting without leaving the page. Latter is pretty nice to have, because ... well ... because it's simply faster and more convenient.

Expanding a section gives the screenshot on the right (pic). To collapse the section, there's a little button in the section header on the right hand side. I'm not 100% convinced it's really needed nor that it's the best solution, but that's how it is at the moment.


I forgot the "how to handle deleted files" section, but it will be in the beta. Not to worry.
Unchanged | Modified
Meet the Preferences.
The Backup Engine section - as simple as it looks, it is fronting a couple of months worth of work and it's easily one of the most complex part of the v2. This is what detaches the user interface from the guts of the program and lets latter run as a separate process.


The Maintenance section - I figured that with the backup being an important piece of software, very few users would be interested in fully automatic updates. Furthermore, quite a few people like to retain even tighter control over the software and, for example, do not like it when the software talks to the Internet whenever it wants. Hence the new option -

Don't check, but remind to check for updates

It's basically a kitchen timer that goes "Ding!" every week or two (configurable) and prompts you to let the app check for a new version. We'll see how it goes, but I think it's a sensible compromise between the privacy and functionality.


The More button transforms the window into a comprehensive list of all available options, close to two dozens now and still counting. The idea however is to keep the defaults reasonable so that there won't be much need to venture into this part of the app.


Lastly, note how the Apply/Close buttons change when the settings are modified. I have no idea why this is not a standard behavior, because it really should be.
A notice | A warning | Alt. dismiss
A message bar is a unobtrusive way to display one-liner messages that would've otherwise required poping up a message box.
When a program detects that it was just restarted with Admin privileges, it has a limited number of options for communicating this joyous news to its user.

#1 - A message box. Bluntly put - I hate them. They are always too sudden, they steal your attention and stuff whatever they want to say down your throat. They ... lack manners.

#2 - A system tray notification. This is less intrusive, but perhaps it's too out of the way. Also, the systray is a shared area so the program is always competing with other apps for the same screen real estate.

#3 - Something else that is right in your field of view if you are looking at the app, but that doesn't get in a way of whatever you are doing at the moment.


Cue in the message bar, now an integral part of the Bvckup UI. It is used for displaying various status notifications right after the launch, after switching the engine to/from the system service mode, when discovering software updates and few other things.

I have also tried the self-closing version of the bar that dismisses itself on a timeout. Like so -
and so -
but having lived with this for a couple of days, it now seems like a solution in a search of a problem. So I shelved it for now. If there's any a real need for this, it'd be very easy to add later on.
Starting up... | Page 1 | Page 2 | Page 3 | Page 4
Nailed down the installer flow. A couple of things of note here.
The most unconventional part of the setup is how it handles the configuration of the installation parameters.

The configuration page (see Page 3) is very bare and focuses on how the program is going to be used instead of being a mixed bag of the minute details of the setup.

The target location is made into a secondary setting with its value controlled by the usage preference. There's no field for the Start Menu group name. There's no ever popular "Run the program after the setup completes" option either. Instead, exiting the setup automatically runs the program (see Page 4), unless the installer window is closed through an (x) at the top.

This leads to a simpler and more intuitive setup flow... or at least that's the idea :)


The installer supports both privileged (administrative) and unprivileged (regular user) installations.

If you are logged in as a regular user and have no rights to modify C:\Program Files, there's no reason why you shouldn't still be able to install a software, just for yourself.

While other installers routinely ask if to install the software for everyone or just for one user, it's a superficial question. It merely controls if the Start Menu group is created under All Users or your personal profile. The program files still go into a system directory and this requires administrative privileges.

Bvckup implements true system- and user- deployment, which is akin to deploying the program in /usr/bin or ~/bin in Unix terms.

In fact, on a multi-user system it is perfectly possible to install one instance of Bvckup for each user and they will all happily co-exist with each other.
The first page of the installer.
Working through the details of the update mechanism.

This is one of more difficult parts of the application, even though on the surface it looks uncomplicated. If we run the installer and it detects that the app is already installed, it should just update the installation. How hard could it be?

Let's see.
If the program is not running, then it's indeed a simple matter of replacing the program file with a newer version. The fun starts if the program is running.

On Windows, running a program locks its file, preventing any changes from being made to it. This is not required per se and there are operating systems that don't do this. There are also custom PE loaders for Windows that can take an executable and create a running process out of it without any locking fuss. For example, bo2k could do that back in 1999. See its source code for details if interested.


To complicate matters, there might be more than one process running off the same executable. For example, if several users are logged into a Windows box and each runs a copy of a program.


Therefore, the first order of business for any installer is to shut down all running instances of the program. A well-behaved installer should also restart all these instances after it's done with updating.


The shutting down part is not a big deal. There's more than one way to do this and all of them are fairly straight-forward.

It's the restarting that is contrived.

Not only program instances may be running under different user accounts, they may also be running with custom command-line arguments, as Administrators or system services. Restarting this cornucopia of awesomeness is not an envious task.


Here's how Bvckup works around this mess.

Every Bvckup executable has a corresponding named event in the Global namespace. The event is created by the first instance of the program when it's launched, and it is opened by all other instances.


The name of the event includes the file ID of the executable file. This groups running instances by the file they are using, because, after all, the installer is interested in a specific executable and nothing else.

For example, the following is an event name used by the Bvckup installation on my development box -

Global\Bvckup2.e65a96a8001f000000013cba.Update


With this in place, the installer starts off by signaling the event.

In response, a running program makes a temporary copy of its executable file and starts it in a special "relauncher" mode. And then it exits.

The "relauncher" process opens the "update" event and simply spins there, waiting for it to become unsignaled.

Meanwhile the installer waits for the program file to become unlocked. Once all running instances replace themselves with the relaunchers, the executable frees up and the installer proceeds with the update. It then clears the "update" event and exits.

This releases the relaunchers, they restart program instances and - ta-da - the update is completed.


Techincally, instead of adding a special "relauncher" mode to the program it's possible just to have a small standalone relauncher program. It comes down to a matter of taste. Some people don't like to spawn from temporary executables, and I like to keep my file count to a bare minimum. To each his own.
Error #1 | #2 | #3 | #4 | #5 | #6
Dotting all i's and crossing all t's, of which there's plenty now that there's an optional system service that just begs to be stopped, restarted and deleted from under app's feet.

Doh... I missed the disabling of the service. Will add it tomorrow.
Redesigned. From this to this.
Vector icons for the website.
This is my first time not using pixel images to decorate a website. Instead, all icons are saved in the SVG format and converted to a webfont, which is then used to style regular HTML characters into icons.

For example, here's a font with the above icon set - VectorIcons.ttf

The advent of webapps like IcoMoon and Fontello not only made the process of building @font-face kits an absolute no-brainer, it also gave an easy access to hundreds of existing vector icons, many of which are free and of production quality.

When coupled with now virtually universal support for CSS text-shadow, box-shadow and gradients, this almost completely eliminates the need for raster form of smaller decorative and nuancing elements.

This is a very big deal and a great time-saver.
Still | Animated | Earlier "final" version
Re-finalized the sign-up form styling and mechanics.
Few styling options for an input control. Leaning towards top right or bottom right, but still need to see what works best in context.
Final design | Starting point
More or less done with the Features section on the new website.

Probably missed few things, but that's easy to add later on. The biggest time sink was trying to inject some visual hierarchy into the list, but without going against overall minimalist look and feel of the site.

Might still revise it after sleeping on it for a couple of days :) Won't be the first time.
Plodding through some grunt work with the new website. An almost equal split between working on a copy, javascript and styling.

As simple as the screencap looks, it came with two hurdles that needed solving.
The header font, Alte Haas Grotesk, didn't display correctly after it was converted to the @font-face kit. Specifically, the lowercase 'o' looked like this:

The font's free, but I couldn't find a copy of its license, so I started tracking down font's author to ask a permission to edit the outlines.

While waiting for a reply, I found another workaround which involved generating the webfont kit from OTFs instead of TTFs. Not a big deal, but it still took over 3 hours to resolve.


The second issue was with the slide-out, fade-in animation. Sometimes the slide-out didn't extend all the way down and sometimes it overshot. This traced back to the fact that slide-out height was computed before the OpenSans was fully loaded and the script fused basic sans-serif to compute the height.

Again, not too complicated, but, again, cost an hour to work through.

:-|

Little bit of this, little bit of that - all unplanned and it all adds up.
Nearly done with the new website design. Here's a snippet of how the site's header interacts with scrolling.
Option 1 | Option 2 | Option 3 | V1 (careful)
First pass over UI styling for the main window.
Released a small playable test of the directory scanning module.

It appears that using as many threads as there are CPU cores and traversing the tree in a depth-first fashion (scan child directories first and sibling directories second) yields the best scanning times.

Test and see for yourself - bvckup2-demo2.exe or 64 bit version.

Also, see here for details.
Updated @bvckup background with V2 branding.
2nd sketch for bvckup2.com redesign. Larger version is here.
1st pass over the redesign of bvckup2.com. Larger version is here.
Current design is almost two years old and it grew steadily disconnected from the simpler aesthetics I am pushing for now. So it needs to be redone.

I will probably simplify this even further. I've been wanting to do a true minimalist site for a software product for a long time now and this seems like a real chance to do just that. Yay.
This is a sprite sheet of all raster images that are going into the run-as-a-service demo.
Interestingly enough, the total size of individual images saved as 32bit PNGs is 63,127 bytes, while the size of this sprite sheet (without checkered backdrop) is 63,829. After factoring in the size of the code that is needed to parse the sprite sheet, it really becomes a no brainer to keep every image in its own file and embed them into .exe's resources that way.
Static | Animated
Added a "crash" handling and reporting facility that includes several important changes compared to the original version:
1. The program now differentiates between three types of errors and handles them slightly differently.

First, there are unexpected operating system errors, i.e. when a core Windows function fails in a way that it shouldn't be failing. Classic example (that everyone is aware of) is TrackPopupMenu that is declared as returning boolean, but actually doesn't shy away from returning an integer under certain circuimstances.

Secondly, there are inconsistencies in app's own code, whereby one part assumes certain usage that is not observed by another part. These are so-called "assert" failures. The original version has three critical issues, all of this particular kind.

Lastly, there are straight-forward crashes. This is when a program is trying to operate with data that is no longer there or corrupted. This is the worst of them all as it typically indicates a major screw up on programmer's part, but in some cases it may also be an indication of failing hardware, like a faulty memory stick.


2. The program now generates a minidump - a small-ish file in a standard Windows format that captures the context of a failure. Minidump files dramatically simplify investigation of a problem on the developer's end.


3. Finally, the minidumps can now be uploaded to the support server right from the error notification window with one click. The transfer is based on WinInet API as this is supposed to improve the chances of getting the report through in proxied and otherwise "enterprised" environments.

For cases when the upload fails, the error dialog also offers an option of opening a link in a regular browser and reporting a problem that way.
64bit version is stored inside of the 32bit executable, from where it is extracted and launched to replace the 32bit version if latter detects that it is being run on a 64bit system.
Pro: a single executable to distribute
Con: the exe comes out weighing twice as much... or does it?

The size of a 32-bit executable can be easily reduced with the help of tools called executable packers. They work by turning the exe file into a self-extracting archive that also automatically launches the original exe after the extraction. It may sound simple but in reality it involves bundling a custom PE loader with the packed executable (as it might not be possible to extract the exe into a temporary file before running it).

In any case, exe packing is routinely used by developers who care about the size of their products, with uTorrent being one of most notable examples. Original Bvckup was also compressed, owning its tiny size in part to the magic of UPX.


The problem lies with 64-bit executables. For a variety of reasons there are presently no exe packers that support them.

However if we store 64bit binary inside of the 32bit executable and then pass latter through a compressor, we end up with both being compressed. Ta-da!

But there's more.


When an .exe is compressed, the compressor leaves the primary application icon intact. This is done so that the app would keep its original appearance in Windows Explorer and not sport a generic "program" icon.

Starting with Vista, the app is expected to support a variety of icon sizes that quickly add up. For example, bvckup's icon weighs in at about 110KB. That's almost half as big as the actual code, the code that does quite a few meaningful things on top of just looking great :)

So, if we do the 64-in-32bit packaging, we end up compressing 64bit version in its entirety, including its icon, and arriving at a greater size reduction if we were to compress the exes separately.

Win-win.
A page from the first demo of Bvckup 2.
Working on a shared memory buffer interface, a part of the IPC module, which is what enables the separation of the engine and the UI.
Option A | Option B
A bit more humane approach to critical error reporting.
The message is a homage to NetPositive, the BeOS browser that pioneered the technique of using haiku in error reporting. In fact, the message in option B is from the NetPoisitive original list.

The icon is that of a Zen circle, which has a plenty of meanings, many of which applicable given the circumstances.
Three-frame animation of engine's heartbeats for the demo.
Page 1 | Page 2
Final UI styling for the "Run As A Service" demo.
The "Run as an Administrator" icon.
Test of a fading transition, part of a small library that deals with supporting UI animations.
Fading animation dissolves a part of a window into background, in preparation for transitioning the window to another state, e.g. moving to the next page in a wizard or resizing the window into a more compact form.

As simple as it sounds, these sort of animation is fairly complex to implement on top of the Windows API.

Windows includes native support for window transparency in a form of layered windows, but it comes with a list of limitations that aren't exactly practical or easy to work, except for several specific cases.

The simplest working solution involves taking a screenshot of the window, creating an overlay window and then using it as a canvas to render the transition from an empty background to the screenshot. All the while making sure that Windows doesn't sneak in an unsolicited window refresh that would lead to a flicker, which in itself is a very "fun" thing to debug.
Every application icon that is exposed to the operating system must exist in at least nine sizes.
16, 32, 48, 256 are more or less expected. These are used in "small", "icon", "tile" and "extra-large " views in Windows Explorer.

20, 22 and 26 are possible sizes of an icon used in the window caption. The exact size depends on screen's DPI level.

And 40 (along with 32 and 48) is the size of an icon used in Alt-Tab view on W7, again depending on the screen's DPI.

If you don't provide an appropriately sized icon, the OS will grab one that is slightly bigger and shrink it down, ruining the pixel polish.

Lastly, each icon ideally must be saved in 32, 8 and 4 bits per pixel formats, so to be compatible... you know... with EGA cards

It would've not that big of a deal if it weren't for the size of a resulting .ico file. For example, the above icon ends up being ~ 120KB, whereas the actual .exe it is attached to and that does quite a few meaningful things sits at around 96KB.
Similarly, every bit of graphics in the app must be done in at least three different sizes - one for each common screen DPI level.
DPI stands for dots-per-inch and it's a metric of a pixel density on the screen. The smaller the screen, the more pixels are packed into a square inch, assuming the resolution stays the same. The difference in DPI between a large LCD panel and a 12" notebook screen can easily be a factor of two or more.

This means that if a program renders 9px text on both screens, on one it will appear twice as small as on the other one, and might command a need for a good magnifying glass.

So naturally it's a good idea to make the OS aware of the actual DPI of the monitor in use. If it's too high, the OS can do few things to make things visible with a naked eye again. Like increase size of the default system font and make windows generally larger.

This can be done automatically by looking at the monitor .inf files or by letting the user configure the DPI manually.


XP defaults to 96 DPI and with some difficulty it can be changed to 120 DPI. Vista and newer versions are better. They come with four predefined levels - 96, 120, 144 and 192 - and they also support custom settings.

This brings us back to needing multiple versions of every graphic in the app.


Vista is the first Windows version to routinely use monitor-specific DPI values out of the box. As such 96 is no longer a dominant DPI level and the apps are now expected to take the DPI into an account when rendering their content.

The higher the DPI, the larger the graphics and the fonts the app should use. The penalty for not doing this is an automatic stretching of the app window that inevitably leads to a blurry appearance and a host of other lovely issues.

In other words - not complying with OS expectations is not really an option. Hence the need for 3+ differently sized copies of the same pixel art.
The UI sketch for run-as-a-service demo.

Trying to find a balance between using custom styling and not getting to far away from the native OS look and feel. See also 8 other options leading up to this one.
Illustrative icons for the same demo.
First pass over the demo UI.
V2 running as a service, an actual screenshot for a change.
Option A | Option B | Option C
Exploration of measured blending of native and custom UI styling.
Option A | Option B
An idea for a space-saving tab control. Shelved.
An idea for an in-form buttons.
Option A | Option B
Exploring full-on customization.
Option A | Option B
Earlier sketches of heavily customized UI.