Kevin Dente's Blog
The Blip in the Noise
-
Things They Didn't Fix in Whidbey - Fonts in Windows Forms
I've been developing with the .NET framework and Visual Studio .NET for several years now. Like most developers, I've accumulated my list of annoyances, hassles, and mistakes that I've encountered using the tools over that time. As an optimistic chap, I cling to the hope that these problems will be addressed in the next version of the toolset.
Well, the next version is here. The improvements are vast, the productivity gains substantial. Naturally, as I've beeng playing with the newest bits (ok, more than play at this point - I'm writing production code on the VS2005 Feb CTP bits), I've been checking to see if MS has addressed any of the problems that have plagued me in the past. Sometimes the news is good, sometimes not. From the title of this post, you can guess which I'm focusing on here. I've already blogged about one such issue. Here's another.
In the .NET Framework 1.x, Windows Forms is really the poor step-child to Web Forms. Yes, MS gave us a reasonably nice object-oriented GUI framework for rich client apps. But let's face it - apps generated with the out-of-the-box controls are the equivalent of circa-1995 Windows applications. One particularly egregious issue with Windows Forms 1.x is with default font handling. Specifically, a Windows Forms application uses the Microsoft Sans Serif font for its controls when running on Windows XP rather than Tahoma, the default system font for XP.
Why is Microsoft Sans Serif used? If you use Reflector to poke in the Control class, you'll find a property called DefaultFont. This is the font that is used if the font isn't explicitly set on the control or its parent. Looking through the source for the property getter, you'll find the following key line of code:
IntPtr ptr1 = UnsafeNativeMethods.GetStockObject(0x11);
So what is stock object 0x11 (decimal 17)? In WinGDI.h, this corresponds to DEFAULT_GUI_FONT. If you look at the MSDN help for GetStockObject, it all becomes clear. Or, maybe not. The first line of help for DEFAULT_GUI_FONT is "Default font for user interface objects such as menus and dialog boxes". OK, that sounds right. Unfortunately, the second two sentences say "This is MS Sans Serif. Compare this with SYSTEM_FONT." So that explains why MS Sans Serif.
Jump down to the description for SYSTEM_FONT, however, and you'll see the following: "By default, the system uses the system font to draw menus, dialog box controls, and text". Erm. Hmm. That sounds familiar, doesn't it? The next two lines clarify "Windows 95/98 and Windows NT: The system font is MS Sans Serif. Windows 2000/XP: The system font is Tahoma".
So it looks suspiciously like someone at Microsoft simply plugged the wrong value into GetStockObject. Now, I'm not a Win32 GDI expert, so maybe there's some history here that explains why they used DEFAULT_GUI_FONT instead of SYSTEM_FONT (Raymond, are you out there?).
OK, so here comes Whidbey. Windows Form 2.0. Finally, Windows Forms gets first class treatment. Slick look-and-feel, richer control set, ClickOnce deployment - MS starts pushing the Smart Client in a big, big way. So of course they're going to fix this font thing, right? Bzzt, sorry, wrong, thank you for playing. No, Windows Forms in Whidbey still uses MS Sans Serif as the default font. In other words, the newest generation of Microsoft's premiere development tool, on Microsoft's latest development platform, generates UIs that don't follow their own UI guidelines.
In all fairness, I'm assuming that MS couldn't change the default font to maintain backward compatibility with existing .NET apps. There's a Ladybug report on this issue describing how to deal with the problem in code, but it's a hack, and there's not a good design-time solution. A small bit of good news is that the new MenuStrip control uses the correct font.
Ideally, I think design-time font selection should work much like color selection, allowing you to select a system font or a custom font. In fact, I started writing a TypeConverter to give you this, but ran into a bug that prevents you from overriding a class TypeConverter with a property TypeConverter. So for the moment there doesn't seem to be a great solution.
-
Visual Studio 2005, Web Sites, and Test-Driven Development
After doing lots of spiking and visual design on a Visual Studio 2005 web site project, I set out to write some production code for the site. I've done some TDD-based component development already on this project, but this was my first foray into writing actual logic (humble dialog style) in the web site project itself. It didn't take long to hit a big snag.
I typically like to put my unit tests in the same assembly being tested. That's always worked well in VS2003, even in web projects, so my first thought was to take the same approach in VS2005. The flaw in that plan is that "building" the web site doesn't generate an assembly that I can point the NUnit test runner at (the assembly ends up in the Temp. ASP.NET Files folder, which isn't too helpful for testing). Oops.
The only solution I've come up with so far is to put the testable UI logic in a separate assembly. Are there any other options that I'm missing?
-
Wow, it finally happened
The good news is that MS finally released their very first ever service pack for a Visual Studio .NET product.
The bad news is that it's Visual Studio .NET 2002 SP1. Presumably VS 2003 SP1 is right around the corner.
And perhaps we shall be free of The Woe at last.
-
DataGridView in Windows Forms 2.0
I finally got a chance to start poking at the new Windows Forms DataGridView control in .NET 2.0. I've only just started with it, but I'm finding it to be a bit of an odd beast.
The .NET 1.1 DataGrid had some major limitations. A big one is that it's fundamentally a data bound control. You can bind it to objects, making it useful without a database, but you can't really use it unbound. The DataGridView addresses this quite well. You can directly create row and cell objects, and it even supports a virtual mode. Nice.
A second big limitation of the DataGrid is that it is column oriented. Creating a column where some cells contain checkboxes and others textboxes is difficult, if not impossible. Again, the DataGridView handles this scenario well.
The design-time experience for the DataGridView is where things get a little weird. At design time, the control still appears as if it's strictly column oriented. When you add columns to the grid, you specify a column type - textbox, checkbox, button, combobox, etc. The cells of that column, however, are not restricted to be of that type. You can add a DataGridViewTextBoxCell to a DataGridViewComboBoxColumn, for example, and it works fine.
Perhaps the assumption is that if you are doing fully unbound data display, you won't use the designer to configure your columns anyway. But you still need to add columns in your code, so you basically just pick a random column type. All-in-all, it makes for an odd overall developer experience. Perhaps something like an UnboundDataGridViewColumn or GenericGridViewColumn that can be added in the designer would be helpful (you can already create a generic DataGridViewColumn, but you still need to specify a cell template, so it doesn't really address the problem).
Three other general comments on the control:
- I really wish MS had included hierarchical support. It's an extremely useful UI model at times (MS uses it in their own apps - Outlook being the most prominent example), and that one missing feature will end up forcing me to use a 3rd party control at some point, I'm sure.
- Creating a custom DataGridViewCell type looks at first glance to be more complex than I would like to see. At least, the Reflector'd implementations of the current cell types are quite complex, essentially doing all of the painting themselves. However, I'm not sure yet if that's a requirement or just for best performance.
- I wish there was a way to plug in a custom column type to the design time experience for the control. Once you start using custom column types, you're pretty much outside of the designer.
-
Add Reference dialog in Visual Studio 2005
Visual Studio 2005 includes some fantastic UI enhancements over VS 2003. One change that I'm not thrilled with is the Add Reference dialog. The 2003 Add Reference dialog included two lists - a list of available components and a list of selected components. You can easily add multiple references by highlighting them in the available components list and clicking Select, at which point they get added to the selected components list.
In VS2005, the dialog changes to only a single, multi-select list (a single list per tab, that is). This is bad. Multi-select lists have poor usability - especially for very long lists (and the default list in 2005 is about 9 pages, which qualifies as long in my book). Selecting multiple items from disjoint sections of the list is difficult, and its easy to accidentally unselected something that you selected three pages back with an errant mouse click. Adding both COM references and .NET references multiplies the problem - now you multiple multi-select lists. I don't know why MS decided to make this change - in my mind, the 2003 version was much more usable.
On the other hand, the references dialog now includes a "recent" tab, listing recently used references. This is a definite usability improvement.
-
IE7 - hard to be excited
Microsoft has announced plans for IE 7, but it's kind of hard to excited about it. Why? Because it's pretty clear that they're being dragged kicking and screaming into it. How can I get excited about using a product that Microsoft clearly isn't excited about creating? I have little faith they they will do much beyond to the absolutely minimum they need to do to stem the migration to Firefox.
-
Cool app - Foxit PDF Reader
Here's a nice little application - Foxit PDF Reader. It's a free, small, fast PDF Viewer. It requires no installation - just dump it into a folder and run it. It wouldn't surprise me if there were some gnarly PDFs that it couldn't handle, but for now it looks good. Adobe's Reader has become a major pig, and it's nice to have an alternative. Recommended.
-
Tip for Windows Forms developers - use Form.CancelButton on your modal dialogs
There's a problem that I encounter with unpleasant frequency using a variety of Windows Forms applications. The problem is that dialog boxes don't dismiss when the escape key is pressed. It's a small thing, but for a keyboard jockey like me, it's very annoying.
The problem occurs when the CancelButton property on the Form isn't set. In a properly coded modal dialog, you set this property to be your cancel button, and the framework handles dismissing the dialog when the escape key is pressed. However, if you directly set the DialogResult of the cancel button to Cancel but don't set the CancelButton property on the form, clicking on the cancel button will dismiss the dialog, but hitting escape will not. If you're only testing with the mouse, everything appears to work as expected.
I reported this as a bug against Whidbey, but MS doesn't seem inclined to change it. So please, people, set that CancelButton property. Take pity on a poor keyboard addicted soul.
-
Separated at birth?
A recent post from Larry Osterman paid tribute to David Weise, one of the legendary engineers at Microsoft. He also linked to article about David, which included a picture. My first reaction was to note a striking resemblence to a well respected.NET blogger. So you tell me - separated at birth? :)
-
My Favorite Firefox Extensions
The Extension architecture is one of the coolest features of Mozilla Firefox. PC Magazine recently published an article rating their top 15 Firefox extensions. I found the list uninspiring - only a couple of the extensions were remotely interesting, and there are many extensions that I like that they didn't list. So here's list of my favorite extensions:
Browsing Enhancments
ieView
I don't like running IE, but there are a few sites that still require it to work properly. Fortunately, with this add-in IE is never more than a click away when you need it.
Focus Last Selected Tab
As far as I'm concerned, FLST makes Firefox behave the way it always should have. With this extension, when you close a tab, the previously active tab gets focus. Particularly useful when searching the web and launching new tabs when exploring search results (something I do a lot).
ImageZoom
Because some times those images are just too darn small. Great for zooming into screenshots.
FlashBlock
I hate navigating to a site and being blasted by a flash animation or ad (especially when they have sound). This extension lets me control when those animations play. It desperately needs a whitelist feature, though - especially since more companies are incorporating flash into regular old business web sites. UPDATE - the latest version does include whitelists. Awesome.
GoogleBar
Because Google is the source of all knowledge.
DuplicateTab
Opens the currently viewed URL in a new tab. Not something that I use constantly, but every once in a while it comes in handy. The "Merge Windows" feature is particularly handy - it combines all the open Firefox windows into one.
AdBlock
Uh - it blocks ads.
Disable Targets for Downloads
Prevents annoying blank tabs from popping up when downloading files from some sites.
ScrapBook
I learned about this one from the PCMag article. Allows you to save a web page or snippet of a page into a library for future viewing and searching.
Web Development Extensions
DOM Inspector
An option in the advanced Firefox install. It gives you a nice tree view of the current DOM document. Very handy.
User Agent Switcher
OK, I haven't actually needed this yet, but it's there just in case. :) Allows you to switch the browser that is reported to the server when requesting pages.
Web Developer
A fantastic grab-bag of developer-related functions. From disabling cookies and scripts to viewing style and tag information, this is a must have extension for web developers.
Live HTTP Headers
View HTTP headers on your web requests - great for troubleshooting problems.
ColorZilla
Another one that I learned about from the PC Mag article. A handy little tool that lets you view the RGB color definition for any point on a page.
Miscelleneous Extensions
ChromEdit
Provides easy access to the various user customization files of Firefox (userChrome.css, user.js, etc)
Gmail Notifier
A fantastic tool for keeping tabs on your Gmail account.
How about you? What extensions do you run?