Tuesday, January 15, 2008

New phone

I received my new phone today, this time I thought I'd try something different for various reasons, so I got a HTC Touch Dual. I haven't really used it enough yet to post any reviews, but first impression is quite nice. Unfortunately it still takes two weeks until I they switch over to the new SIM card (due to carrier change), so until then I cannot really use it fully. But yes, I will keep my old number...

On a related note, things don't seem as bright with the handsfree that I got, it was cheap yes, but first it had the wrong kind of mains plug on the charger, and secondly after I found an appropriate adapter, the thing won't charge !?!

Monday, January 14, 2008

Maximizing a WPF Window to second monitor

I'm trying to develop and application that utilizes a maximized window on the second monitor.

There's a few issues here. The first is that WPF doesn't offer the same information as WinForms about monitor configuration. WinForms has SystemInformation.MonitorCount and Screen.AllScreens[i].WorkingArea. WPF has SystemParameters.PrimaryScreen[Width/Height] and SystemParameters.VirtualScreen[Width/Height] which almost works (as long as you don't have more than two monitors) but not really. So back to using WinForms API...

Secondly, the obvious solution to display a form maximized on second screen was to me the following:

                fullScreenWindow.WindowStartupLocation = WindowStartupLocation.Manual;

Debug.Assert(System.Windows.Forms.SystemInformation.MonitorCount > 1);

System.Drawing.Rectangle workingArea = System.Windows.Forms.Screen.AllScreens[1].WorkingArea;
fullScreenWindow.Left = workingArea.Left;
fullScreenWindow.Top = workingArea.Top;
fullScreenWindow.Width = workingArea.Width;
fullScreenWindow.Height = workingArea.Height;
fullScreenWindow.WindowState = WindowState.Maximized;
fullScreenWindow.WindowStyle = WindowStyle.None;
fullScreenWindow.Topmost = true;

However, when you try that you'll end up with a topmost maximized window on your primary display, which was not what we wanted.

Turns out that we cannot maximize the window until it's loaded. So by hooking the Loaded event of fullScreenWindow and handling the event along the lines of:

        private void Window_Loaded(object sender, RoutedEventArgs e) {
WindowState = WindowState.Maximized;

...it works.

Oh, and you want to make certain that you are running a dual monitor configuration so you do not put the window somewhere where it is off-screen.

Wednesday, January 09, 2008

UIAutomation - testing Calculator

I recently discovered that the UIAutomation library provided in .NET 3.0 doesn't only work for managed code but for any code.

Should you so be inclined, here's how to test that calc.exe provided by Windows in fact can calculate 2+2 correctly.

public void TestAddTwoAndTwo() {

Process calc = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = @"c:\windows\system32\calc.exe";
calc.StartInfo = startInfo;

AutomationElement window = AutomationElement.FromHandle(calc.MainWindowHandle);
AutomationElement twoButton = FindAutomationElementByName(window, "2");
AutomationElement plusButton = FindAutomationElementByName(window, "+");
AutomationElement equalsButton = FindAutomationElementByName(window, "=");

AutomationElement editField = window.FindFirst(TreeScope.Descendants, new AndCondition(
new PropertyCondition(AutomationElement.ClassNameProperty, "Edit"),
new PropertyCondition(AutomationElement.IsValuePatternAvailableProperty, true)));

InvokePattern clickTwo = twoButton.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
InvokePattern clickEquals = equalsButton.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
InvokePattern clickPlus = plusButton.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;




ValuePattern pattern = editField.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;

Assert.AreEqual(4, int.Parse(pattern.Current.Value,NumberStyles.AllowDecimalPoint|NumberStyles.AllowTrailingWhite));
        public AutomationElement FindAutomationElementByName(AutomationElement parent, string name) {
Condition c = new PropertyCondition(AutomationElement.NameProperty, name);
return parent.FindFirst(TreeScope.Descendants, c);

You'll also want a reference to UIAutomationClient.dll and the following using:

using System.Windows.Automation;

To find out what the application under test has eaten i.e. how to automate it, do use UISpy.exe provided with the Windows SDK .

And yes, the syntax is a tad verbose ...

Tuesday, January 08, 2008

LINQPad - Useful Linq tool

If you are using LINQ (or want to try it) and want to try out your query expressions dynamically you'll want to check out LINQPad.

Free (as in beer) and very useful!

Sunday, January 06, 2008

LINQ - DataContext.Dispose()

I'm playing around with LINQ for the moment. Actually I tried Entity Framework first, but could not get that to behave as I wanted (that is Table Per Class), so I let that rest for a while until they fix TPC support in a subsequent version and tried "plain" LINQ instead.

I can't say I'm really there yet, but one thing that bit me was that I out of old habit (or whatever) used code similar to the following:

            using (DataClassesDataContext db = new DataClassesDataContext();
return (from user in db.Users
where user.Name == name
select user).SingleOrDefault();

..and I thought that all was well. However, when testing a little bit more I got  ObjectDisposedException:s when returning

return (from user in db.Users select user).AsEnumerable();

instead of

return (from user in db.Users select user).ToList();

Turns out that even though DataContext implements IDisposable, you should not use a DataContext in a using statement or directly call .Dispose() or you'll end up with lots of brokenness.

(In addition I got all kinds of attaching and detaching issues, but I think I've sorted them now. Did I already tell you that this is my first attempt of using LINQ non-trivially?)