Scott Hanselman

WPF and Text Blurriness, now with complete Clarity

March 9, '10 Comments [25] Posted in VS2010 | Windows Client | WPF
Sponsored By

shanselman - Evernote The #1 complaint I hear about WPF (Windows Presentation Foundation) is that many fonts end up looking "blurry." It's a darned shame because really great applications like Evernote get criticized because of this one issue*.

The blurriness happens on .NET 3.5 and below because WPF's graphics system is "device independent" so rendering happens independent of resolution. It makes apps DPI-aware for free and scales them nicely. Unfortunately MOST people are running on 96dpi screens and that's where you'd expect clarity. You can get around this 90% of the time today using SnapsToDevicePixels when appropriate, but it wasn't automatic and it's subtle.

The good news is that with .NET 4 this is totally fixed. You can see with with the .NET 4 RC (Release Candidate) and VS2010, which uses WPF for much of its own rendering. Additionally, a check-in in a recent milestone makes things even clearer with light text on a dark background.

From the WPF Text Blog:

"With this fixed, WPF is not technically pixel perfect with GDI text rendering, but the difference is indiscernible to the naked eye."

So how indiscernible?

UPDATE: A little confusion about this in the comments. Folks feel very strongly about this stuff, understandably. Just like color blindness, some people are sensitive to this stuff and others "can't see it." One person in the blogs didn't like go for "indiscernible" and showed a screenshot. Here's the deal. If you are running VS2010 RC, you don't have this fix. This will be in the RTM. Here's a 100% screenshot, followed by the zoomed in version. The takeaway is this. If you didn't like the rendering before, you will now. This is/was some subtle stuff, but it's indiscernible in the RTM, so be happy! I took the screenshot from a daily build, not the actual RTM, which hasn't happened yet.

image

Blown up:

image

Click on these side-by-side images from the WPF Text Blog to enlarge and compare. VS2008 with GDI rendering is on the left and VS2010 (a post RC-build) with this fix is on the right. Of course, the release of .NET 4 will have this fix.

White Background Dark Background

In the comments on the WPF Text Blog, Rick Brewster, the author of Paint.NET suggests that we can really analyze these images using an XOR in Paint.NET.

I've done just that here, taking the dark text on a white background and XORing it. Then, for visibility, I've inverted the result. This shows just the differences in pixels between the two rendering paths. Can't see much? That's the point.

XOR and Inverted Text between the GDI and WPF rendering paths in VS2010 and .NET 4 WPF

To quote from the WPF Blog comments: "If you can’t tell a difference between the screenshots of VS2008 and VS2010, then you should not be able to tell the difference between GDI and another WPF app."

Also, note that this applies to all WPF apps on .NET 4. It's a general fix that's not VS2010 specific. Enjoy. I'll be happy when this is out and everyone's using it, including my favorite WPF app, Evernote.

* I don't know anyone at Evernote, I'm just a fan and I read the comments on their blog. I speak only for me on this issue.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

A Trip Down Memory Lane - Presentations over 10 years old

March 9, '10 Comments [31] Posted in Speaking
Sponsored By

I've been presenting for a long time. It's great fun, mostly it's stand-up comedy with code and PowerPoint. I also keep everything, always, so earlier today when I was asked by a friend to find some ten year old code, I found a few 10 year old "Company Confidential" PowerPoint presentations. Not only was I shocked and offended by my sense of style (what was I thinking) but the scope of "Ten Years" really hit me. Ten Years is no time at all.

Here's a bit of what I found from 1999 and earlier. This is from a presentation on Windows 98 and what developers need to know.

"This screen shot is from a system with 8 gigs!"

 "This screen shot is from a system with 8 gigs!"

Some things never change...

Most apps don't handle power management well.

Oh, my.

Windows DNA

Man, these were the days:

How does ASP work?

This analogy made sense in 1998.

Apples to Apple Juice

Oh, is THAT how you design for scalability?

Designing for Scalabilty?

I remember squeezing COM for performance...

Smarter COM Strategies

More importantly: What were you doing, coding, writing about or presenting about ten+ years ago, Dear Reader?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Video Trip Report: If this is Tuesday, this must be Cairo

March 6, '10 Comments [11] Posted in ASP.NET | ASP.NET Ajax | ASP.NET MVC | Channel9 | Screencasts | Speaking | TechEd | Windows Client
Sponsored By

image

This last week over a 7 day period, I went to Munich, Cairo and Dubai. I presented in three keynotes and did a total of 10 sessions. I crossed 12 time zones and missed my kids. I talked to/with/at about 3000 people.

I'm utterly shattered.

I took some video while I was travelling with my Creative Vado HD and slapped it into Windows Live Movie Maker just now. Here's my trip montage.

You could call this either "The Glamourous Life of a Technical Speaker" or "If this is Tuesday, this must be Cairo" or "Scott needs to learn to say No."

It was great fun, I spoke at VSOne in Munich. I talked about .NET 4 and ASP.NET MVC. We also had a nice Nerd Dinnner. Then I headed over to Cairo Code Camp and the turnout was HUGE. Something like 700-800 folks showed up at the German University in Cairo. I also recorded a great podcast on Women in Technology in the Muslim World. Then I headed to Dubai for TechEd Middle East where I presented in three sessions and did the keynote demo for Soma. It's always a challenge for me to travel because of my diabetes, particularly because of the time zones but also sitting for 16 hours at a time in a plane and eating plane food is a problematic. However, I must say that everyone on this trip was incredibly kind and accommodating.

If you have the chance to go to Munich, Cairo, and/or Dubai, I highly recommend it. The people, the places and the technologists are all top-notch.

Enjoy.

P.S. Thanks to http://blog.bloggingitloud.com/ for the guerilla footage of the TechEdME Keynote.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Hanselminutes Podcast 203 - Women in Technology in the Muslim World

March 5, '10 Comments [12] Posted in Africa | Podcast | Programming
Sponsored By

Abeer and Lamees My two-hundred-and-third podcast is up. I was in Egypt and had the opportunity to sit down with Lamees and Abeer, two successful women in IT. Lamees is a programmer transitioning to Systems Analysis, and Abeer is a veteran Senior Systems Analyst and Agile Project Manager at Dashsoft. Nearly 50% of the people at Cairo Code Camp are women. What is Egypt doing right to encourage so many women to choose technology as their career?

Subscribe: Subscribe to Hanselminutes Subscribe to my Podcast in iTunes

Download: MP3 Full Show

Do also remember the complete archives are always up and they have PDF Transcripts, a little known feature that show up a few weeks after each show.

I want to add a big thanks to Telerik. Without their support, there wouldn't be a Hanselminutes. I hope they, and you, know that. Someone's gotta pay the bandwidth. Thanks also to Carl Franklin for all his support over these last 4 years!

Telerik is our sponsor for this show.

Building quality software is never easy. It requires skills and imagination. We cannot promise to improve your skills, but when it comes to User Interface and developer tools, we can provide the building blocks to take your application a step closer to your imagination. Explore the leading UI suites for ASP.NET AJAX,MVC,Silverlight, Windows Forms and WPF. Enjoy developer tools like .NET reporting, ORM,Automated Testing Tools, TFS, and Content Management Solution. And now you can increase your productivity with JustCode, Telerik’s new productivity tool for code analysis and refactoring. Visit www.telerik.com.

As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

Enjoy. Who knows what'll happen in the next show?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

The Weekly Source Code 51 - Asynchronous Database Access and LINQ to SQL Fun

March 2, '10 Comments [25] Posted in ASP.NET | ASP.NET MVC | LINQ | Open Source | Source Code
Sponsored By

You can learn a lot by reading other people's source code. That's the idea behind this series, "The Weekly Source Code." You can certainly become a better programmer by writing code but I think good writers become better by reading as much as they can.

I was poking around in the WebFormsMVP project's code and noticed an interesting pattern.

You've seen code to get data from a database and retrieve it as an object, like this:

public Widget Find(int id)
{
Widget widget = null;
widget = (from w in _db.Widgets
where w.Id == id
select w).SingleOrDefault();
return widget;
}

This code is synchronous, meaning basically that it'll happen on the same thread and we'll wait around until it's finished. Now, here's an asynchronous version of the same code. It's a nice combination of the the new (LINQ, in this case, LINQ to SQL) and the older (DataReaders, etc). The LINQ (to SQL) query is in query, then they call GetCommand to get the underlying SqlCommand for that query. Then, they call BeginExecuteReader on the SqlCommand which starts asynchronous execution of that command.

SqlCommand _beginFindCmd = null;

public IAsyncResult BeginFind(int id, AsyncCallback callback, Object asyncState)
{
var query = from w in _db.Widgets
where w.Id == id
select w;
_beginFindCmd = _db.GetCommand(query) as SqlCommand;
_db.Connection.Open();
return _beginFindCmd.BeginExecuteReader(callback, asyncState, System.Data.CommandBehavior.CloseConnection);
}

public Widget EndFind(IAsyncResult result)
{
var rdr = _beginFindCmd.EndExecuteReader(result);
var widget = (from w in _db.Translate<Widget>(rdr)
select w).SingleOrDefault();
rdr.Close();
return widget;
}

When it's done, in this example, EndFind gets called and they call DataContext.Translate<T> passing in the type they want (Widget) and the source, the DataReader retrieved from EndExecuteReader. It's an asynchronous LINQ to SQL call.

I found it clever so I emailed my parallelism friend and expert Stephen Toub and asked him if this was any or all of the following:

a. clever

b. necessary

c. better done with PFX/TPL (Parallel Extensions to the .NET Framework/Task Parallel Library)

Stephen said, in his own get-down-to-business fashion:

a) It's a standard approach to converting a LINQ query to a command to be executed with more control over how it's executed.  That said, I don't see it done all that much, so in that capacity it's clever.

b) It's necessary to run the query asynchronously; otherwise, the call to MoveNext on the enumerator will block. And if ADO.NET's MARS support is used (multiple asynchronous result sets), you could have multiple outstanding operations in play.

c) TPL can't improve upon the interactions with SQL Server, i.e. BeginExecuteReader will still need to be called.  However, TPL can be used to wrap the call such that you get a Task<Widget> back, which might be a nicer API to consume.  Once you have it as a Task, you can do useful things like wait for it, schedule work for when its done, wait for multiple operations or schedule work when multiple operations are done, etc.

One other thing that's interesting, is the WebFormsMVP project's PageAsyncTaskManagerWrapper:

namespace WebFormsMvp.Web
{
/// <summary>
/// Represents a class that wraps the page's async task methods
/// </summary>
public class PageAsyncTaskManagerWrapper : IAsyncTaskManager
{
readonly Page page;

/// <summary />
public PageAsyncTaskManagerWrapper(Page page)
{
this.page = page;
}

/// <summary>
/// Starts the execution of an asynchronous task.
/// </summary>
public void ExecuteRegisteredAsyncTasks()
{
page.ExecuteRegisteredAsyncTasks();
}

/// <summary>
/// Registers a new asynchronous task with the page.
/// </summary>
/// <param name="beginHandler">The handler to call when beginning an asynchronous task.</param>
/// <param name="endHandler">The handler to call when the task is completed successfully within the time-out period.</param>
/// <param name="timeout">The handler to call when the task is not completed successfully within the time-out period.</param>
/// <param name="state">The object that represents the state of the task.</param>
/// <param name="executeInParallel">The vlaue that indicates whether the task can be executed in parallel with other tasks.</param>
public void RegisterAsyncTask(BeginEventHandler beginHandler, EndEventHandler endHandler, EndEventHandler timeout, object state, bool executeInParallel)
{
page.RegisterAsyncTask(new PageAsyncTask(beginHandler, endHandler, timeout, state, executeInParallel));
}
}
}

They made a nice wrapper for these existing System.Web.UI.Page methods and they use it like this, combined with the asynchronous LINQ to SQL from earlier:

AsyncManager.RegisterAsyncTask(
(asyncSender, ea, callback, state) => // Begin
{
return widgetRepository.BeginFindByName(e.Name, callback, state);
},
result => // End
{
var widget = widgetRepository.EndFindByName(result);
if (widget != null)
{
View.Model.Widgets.Add(widget);
}
},
result => { } // Timeout
, null, false);
AsyncManager.ExecuteRegisteredAsyncTasks();

They fire off their task, which then does its database work asynchronously, and then it all comes together.

I'll leave (for now) the wrapping of the APIs to return a Task<TResult> as an exercise for the reader, but it'd be nice to see if this pattern can benefit from the Task Parallel Library or not.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.