In the Year 2011

Illustration

As usual, first post in 2012 is great chance to recapitulate what was going on in previous year.

There was total of 106 posts (which is slight decrease from last year) with around 40% of them being related to programming and 10% being related to my programs. Rest of posts is anybody’s guess - I am annoyingly bad at assigning categories to posts. Improving on that might even be my New Year’s resolution. And, as it happens with all of those, it will fail miserably. :)

Total number of visits has increased to 90,000 (from 54,000 last year) so I would say that blog has some traction going. Search engines bring little bit over 50% of traffic (90% of that being from Google). Referral sites bring 30% which means that there is almost 20% of people who enter this link directly.

Analysis says that 25% of you are from United States, 10% from Germany and further 30% from all around world. My own country (Croatia) brings 2.7% to the table. That leaves something like 35% of people that have no location on this world. Either browsers got better at hiding their tracks or aliens just love my blog. :)

Internet Explorer still leads in browser wars with 36% of visitors using it. I was pleasantly surprised that majority of those using it were at version 8 (55%) or version 9 (33%). That leaves only 12% for older versions of IE. Firefox was second with 33% and my favorite Chrome was third with 25% of a pie.

This year also marks special moment for me - I left Blogger platform for self-hosted WordPress site. This step included not only efforts of installing WordPress (which was really easy) but also manual conversion of 340+ posts. And it was worth it since WordPress gives me much better control over almost every aspect of my blog, since speed is improved, since I was able to integrate everything with my old site, and list goes on and on. Only downside is that I am now responsible for making backups and paying for hosting costs but it is small price to pay (and one can always make a donation).

Happy new year to everyone.

OpenFolderDialog

Illustration

I hate FolderBrowserDialog. It is limited, ugly and stuck in Windows 2000 GUI. Whenever I had to select folder, I would resort to using SaveFileDialog instead. User would select any file name and I would just use directory part. It was non-optimal but still better than FolderBrowserDialog.

Vista brought new common file dialogs but I pretty much ignored them - most of my programs need to run under XP so there was not much benefit in using Windows Vista specific controls. However, those controls had special mode that finally brings folder selection in normal FileOpenDialog.

Code (after you define all needed COM interfaces) is actually quite straightforward. Once FOS_PICKFOLDERS is set, half of work is done. All other code is just plumbing to show the form and get user’s selection in form of path.

var frm = (IFileDialog)(new FileOpenDialogRCW());
uint options;
frm.GetOptions(out options);
options |= FOS_PICKFOLDERS;
frm.SetOptions(options);

if (frm.Show(owner.Handle) == S_OK) {
    IShellItem shellItem;
    frm.GetResult(out shellItem);
    IntPtr pszString;
    shellItem.GetDisplayName(SIGDN_FILESYSPATH, out pszString);
    this.Folder = Marshal.PtrToStringAuto(pszString);
}

Full code with Windows XP compatibility and little bit more error checking is available for download. However do notice that all unneeded COM fat has been trimmed in order to have it concise. Short and sweet I say.

[2012-02-12: Fixed bug in source code.]

QText 2.50

Illustration

QText is improved once more. There are no bigger changes (I am holding them for 3.00 :)) but many will enjoy fixed text manipulation. It is shame to admit that multiline tabs were fundamentally broken for few versions now.

Finally there is upgrade procedure in place. It is not automatic but requires user interaction. I like it better that way but I am open for other suggestions.

Other notable changes include quite a few interface tweaks and bug-fixes.

Try it.

Downloading File With Progress

As I was creating upgrade procedure for few programs of mine I had a need to download file. With progress bar. Most of you can already see a solution: HttpWebRequest in BackgroundWorker.

Base idea is creation of HttpWebRequest, getting it’s response as stream and iterating through all bytes until we read them all. Heart of (DoWork) code is:

var request = (HttpWebRequest)HttpWebRequest.Create(url);
using (var response = (HttpWebResponse)request.GetResponse()) {
    using (var stream = response.GetResponseStream()) {
        using (var bytes = new MemoryStream()) {
            var buffer = new byte[256];
            while (bytes.Length < response.ContentLength) {
                var read = stream.Read(buffer, 0, buffer.Length);
                if (read > 0) {
                    bytes.Write(buffer, 0, read);
                    bcwDownload.ReportProgress((int)(bytes.Length * 100 / len));
                } else {
                    break;
                }
            }
        }
    }
}

Before we send result back to RunWorkerCompleted event we need to get file name that was actually delivered. While this step is optional, I find it especially useful if there are some redirections on web site (e.g. pointing you to newer version of file):

[csharp highlight=“1”] string fileName = response.ResponseUri.Segments[response.ResponseUri.Segments.Length - 1]; e.Result = new DownloadResult(fileName, bytes.ToArray()); [/csharp]

P.S. Do notice that DownloadResult is our own class - there is no such class in .NET Framework.

In RunWorkerCompleted we only must save file as such:

var res = (DownloadResult)e.Result;
var file = new FileInfo(res.FileName);
using (var frm = new SaveFileDialog() { FileName = file.Name }) {
    if (frm.ShowDialog(this) == DialogResult.OK) {
        File.WriteAllBytes(frm.FileName, res.Bytes);
        MessageBox.Show(this, "Done.", "Something", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
}

And with that you have your file downloaded.

Full source code (with all missing parts of code) is available for download.

Mercurial Keyring

There is one non-intuitive thing with securing Mercurial. You should remove all authentication data from URL and TortoiseHg will actively enforce it (assuming that you are Yes guy). However even with mercurial_keyring extension enabled it will ask for a user name and password. And it will ask every time you push.

Don’t worry. It isn’t that mercurial_keyring extension is broken, we are just missing some data in %USERPROFILE%\mercurial.ini configuration file:

[extensions]
mercurial_keyring = 

[auth]
bb.schemes = http https
bb.prefix = bitbucket.org
bb.username = jmedved

Example above is something I use for BitBucket but it is applicable for any other server. Only thing that needs to change is prefix (bb in this case) that needs to be unique within configuration file and prefix of your server.