Tuesday, March 07, 2006

Does your new Dell high resolution LCD display graphics within Internet Explorer that look like this?


Your computer manufacturer has enabled a setting within IE that attempts to scale graphics to their original intended size by correcting for your wide aspect or high resolution display. You can turn it off with the following registry hack. Graphics will now appear smaller but clean.

REGEDIT4
[HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main]
"UseHR"=dword:00000000

Download the Reg files here:
http://download.binaryocean.com/IEUseHR.zip

kick it on DotNetKicks.com   Tuesday, March 07, 2006 10:54:21 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [2]  | 
 Monday, February 27, 2006

This is a bit off topic:

My old Nokia 6xxx series phone gave me many years of service before the seal between the LCD and the outer plastic clear screen finally went. The phone collected lint from my pocket rendering it unreadable in direct sunlight. I could pop off the back and front covers and clean the screen but would only get a few days out of it. Maybe I needed to work on my laundering technique instead? Time for a new phone...

I have always wanted a Microsoft Windows Mobile Smartphone so I decided to give the Cingular 2125 a try. A phone that I could program with the CF and sync with all my Outlook contacts! To top things off, Cingular is currently offering their Media Net unlimited data plan for $20 per month so now I could even read my email. Seemed like a no brainer to me.

At first I really loved the phone. The display is bright and beautiful. The much talked about power button isn't really that bad. You just need to realize that the button is really just a bump on the hard plastic strip that runs across the top of the phone. To push it, push perpendicular to the plastic strip and not the faux button. The strip is attached and hinges slightly at the right hand side of the phone. The faux button is on the left and is more of a guide than anything else. I was able to set up the phone and sync to my back end Exchange server without much effort.

The Dark Side: After using the phone for a day, I found that my average to slightly large hands were just too big for those tiny keys. The phone is almost the same size as my previous Nokia but the screen takes up most of that real estate. I also found that about 35% of the time I would make the wrong selection with the little joy stick (another result of the large screen and small key area.) Lastly, the Media Net access was painfully slow. I was quickly regretting my choice.

I returned the phone and exchanged the 2125 for a Motorola RAZR which seemed like a much better fit for my fingers and hands. I also went with the RAZR because it is the same phone that my wife has and having a single set of chargers and connectors is nice. My only complaint with the phone is that you can't page in the address book and scrolling a contact line at a time is very slow.

One other minor complaint about the RAZR is that Motorola decided to orient the LCD (and front polarization) at 90 degrees to what is normally done. On most of the active LCDs that I have used, the screen gets brighter and darker as you change the angle of tilt by moving the top of the screen closer and further away from you but when you do this on the RAZR, the brightness remains relatively constant. On most LCDs as you move from left to right the brightness remains constant at least until you move way out to one side or the other. Again, my RAZR exhibits exactly the opposite behavior. I notice a subtle difference in the brightness of the image viewed by my left and right eyes. I am guessing that Motorola did this to better handle the "flip" aspect and thus the different vertical viewing angles of the phone?

If Motorola were to put Windows Mobile on the RAZR form factor, they would have a big hit.

kick it on DotNetKicks.com   Monday, February 27, 2006 9:24:19 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [1]  | 
 Thursday, February 16, 2006

Just came across this little generic gem:

string[] input = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };

int[] output = Array.ConvertAll<string, int>(input, delegate(string s) { return int.Parse(s); });

 

I have a number of web.config files that store lists of integers as comma separated strings. This is a clean way to convert it all to an int array. (It is in need of some exception handling.)

 

<appSettings>

      <add key="MachineIDs" value="44,3,43,566" />

</appSettings>

 

private int[] GetConfigIntArray(string key)

{

    string[] values  = ConfigurationManager.AppSettings[key].Split(',');

    return Array.ConvertAll<string, int>(values, delegate(string s) { return int.Parse(s); });

}

kick it on DotNetKicks.com   Thursday, February 16, 2006 10:46:59 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [5]  | 
 Tuesday, January 31, 2006

Seems that everyone is getting into it:

  Microsoft IBM Oracle
Product Name SQL Server Express 2005 IBM DB2 Express-C Oracle Database 10g Express Edition (XE) (beta)
Version 9.0.1399 8.2 10g (beta)
Max DB Size 4 GB Unlimited 4 GB
Max RAM 1 GB 4 GB 1 GB
Max CPUs 1 2 1
Max Users Unlimited Unlimited Unlimited
Instances Unlimited Unlimited 1
Price Free Free Free
  Download Download Download
kick it on DotNetKicks.com   Tuesday, January 31, 2006 4:37:30 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [1]  | 
 Friday, January 27, 2006

This is one that has been driving me crazy for a few weeks. I finally decided to get to the root of it:

I have an ODS control that sits between a GridView and a data class that returns a DataTable. I manipulate the datatable in the ObjectDataSource_Selected event. If my data class throws an exception, I never see it, however I receive a "System.NullReferenceException: Object reference not set to an instance of an object." when attempting to access the Rows.Count property within the ODS Selected event:

protected void ObjectDataSourceMain_Selected(object sender, ObjectDataSourceStatusEventArgs e)

{

    DataTable dataTable = (DataTable)e.ReturnValue;

 

    if (dataTable.Rows.Count == 0) // <- Exception!

    {

        // ...

    }

}

 

The solution involves checking the e.Exception property and throwing the exception when e.Exception is not null. In this case I receive the offending "System.Data.SqlClient.SqlException: Invalid column name 'CcontentID'." exception:

 

protected void ObjectDataSourceMain_Selected(object sender, ObjectDataSourceStatusEventArgs e)

{

    if (e.Exception != null)

    {

        throw e.Exception;

    }

 

    DataTable dataTable = (DataTable)e.ReturnValue;

 

    if (dataTable.Rows.Count == 0)

    {

        // ...

    }

}

kick it on DotNetKicks.com   Friday, January 27, 2006 3:54:10 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [5]  | 
 Sunday, January 22, 2006

I am working on a control that passes a small amount of encrypted data in the url. No need to encrypt it while running under the local Visual Studio Web Server. You can check to see if 

System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName

returns 'WebDev.WebServer.EXE'. Cool little piece of code. Full details on Steven Smith's blog:

http://aspadvice.com/blogs/ssmith/

kick it on DotNetKicks.com   Sunday, January 22, 2006 2:12:09 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
 Thursday, January 19, 2006

NOTE: I have been receiving a lot of traffic on this posting and don't see (m)any other solutions out there so I decided to port the code to Visual Basic and repost the entry. Most of the writeup is in C#, but a VB solution is included in the download. Sorry for the VB gripes, but I am trying to learn a bit here.... On another note, is reposting a social faux pas in the blog world?


I frequently use an ASP.NET TreeView as a navigation menu. This works well on a single page but if you include the control on a Master Page, it looses its expansion state as you move from one content page to another.

After populating my TreeView, either expand or collapse all of the nodes to insure that there is a consistent default behavior. Then restore your TreeView expansion state to a previously saved state by invoking the RestoreTreeView method of the TreeViewState class:

// set the default state of all nodes.

TreeViewMain.CollapseAll();

 

// get the saved state of all nodes.

new TreeViewState().RestoreTreeView(TreeViewMain, this.GetType().ToString());

Before navigating to a new page, save the existing state for future use but first you need to overcome the urge to use the NavigateUrl property on a TreeNode. Using this property will generate an HTML hyperlink tag on your TreeView which will cause the browser to initiate the transfer to the new Url. Control is not returned to the server and you will never have the opportunity to save the existing state. Instead, wire up the TreeView_SelectedNodeChanged event for the TreeView, put your page address into the Node.Value property and use a Response.Redirect():

protected void TreeViewMain_SelectedNodeChanged(object sender, EventArgs e)

{

    if (TreeViewMain.SelectedNode.Value != string.Empty)

    {

        Response.Redirect(TreeViewMain.SelectedNode.Value);

    }

}

Next, save the TreeView state by subscribing to the TreeView_Unload event. This event is fired just before the control is unloaded from memory. Pass your TreeView to the SaveTreeView method of the TreeViewState class:

protected void TreeViewMain_Unload(object sender, EventArgs e)

{

    // save the state of all nodes.

    new TreeViewState().SaveTreeView(TreeViewMain, this.GetType().ToString());

}

 

Within the SaveTreeView and RestoreTreeView methods of the class, I recursively walk the nodes collection and either save or restore the TreeNode.Expanded property in/from a generic list of type <bool?>. The TreeNode uses a nullable boolean value to store this state so I used the same type in a List.

The expansion state is saved in a Session variable. It is possible that you will want to save the state for two identically named TreeView controls on different master pages within your application. This would cause an issue with the name of the Session variable so I included a 'key' parameter that is concatenated with the ID of the TreeView to form the name of the session variable. You can pass any string value as the key, but using the name of the invoking master page class should eliminate most conflicts. I coded this as 'this.GetType().ToString()' which will return a string of the class type.

Lastly, if the number of nodes exceeds the element count in the List<> object, I simply return from the method. This might happen if the data source for your TreeView changes on the fly. If your data source if routinely changing, you will need to tweak the class to better handle this scenario.

As I indicated earlier, I have now included a VB.NET version of the solution. This is the most VB that I have coded since moving from VB6 to C# when I made the jump to .NET in the early beta days sometime in 2001. I love the simple syntax of C# compared to the wordiness of VB. Take a look as how the two handle generic collections:

VB.NET:

 

Public Sub RestoreTreeView(ByVal treeView As TreeView, ByVal key As String)

    Dim list As New List(Of Nullable(Of Boolean))

    If HttpContext.Current.Session(key + treeView.ID) IsNot Nothing Then

        list = CType(HttpContext.Current.Session(key + treeView.ID), List(Of Nullable(Of Boolean)))

    End If

 

    RestoreTreeViewIndex = 0

    RestoreTreeViewExpandedState(treeView.Nodes, list)

End Sub


C#:

 

public void RestoreTreeView(TreeView treeView, string key)

{

    RestoreTreeViewIndex = 0;

    RestoreTreeViewExpandedState(treeView.Nodes,

        (List<bool?>)HttpContext.Current.Session[key + treeView.ID] ?? new List<bool?>());

}

Is there a cleaner way of doing this in VB? Please let me know. Also is there a way of instantiating a class and invoking a method in one statement in VB.NET?

VB.NET:

Dim treeViewState As New TreeViewState()

treeViewState.SaveTreeView(TreeViewMain, Me.GetType.ToString())

 

C#:

new TreeViewState().SaveTreeView(TreeViewMain, this.GetType().ToString());

I am the first to admit that VB.NET has its place. I know that when it is time to work with Office automation, I will be using VB.NET so please, no holy wars.

Download the complete CS and VB solutions:
http://download.binaryocean.com/TreeViewSaveStateSolution.zip

Here is the complete CS class. The VB version is included in the download:

using System;

using System.Collections.Generic;

using System.Web;

using System.Web.UI.WebControls;

 

public class TreeViewState

{

    public void SaveTreeView(TreeView treeView, string key)

    {

        List<bool?> list = new List<bool?>();

        SaveTreeViewExpandedState(treeView.Nodes, list);

        HttpContext.Current.Session[key + treeView.ID] = list;

    }

 

    private int RestoreTreeViewIndex;

 

    public void RestoreTreeView(TreeView treeView, string key)

    {

        RestoreTreeViewIndex = 0;

        RestoreTreeViewExpandedState(treeView.Nodes,

            (List<bool?>)HttpContext.Current.Session[key + treeView.ID] ?? new List<bool?>());

    }

 

    private void SaveTreeViewExpandedState(TreeNodeCollection nodes, List<bool?> list)

    {

        foreach (TreeNode node in nodes)

        {

            list.Add(node.Expanded);

            if (node.ChildNodes.Count > 0)

            {

                SaveTreeViewExpandedState(node.ChildNodes, list);

            }

        }

    }

 

    private void RestoreTreeViewExpandedState(TreeNodeCollection nodes, List<bool?> list)

    {

        foreach (TreeNode node in nodes)

        {

            if (RestoreTreeViewIndex >= list.Count) break;

 

            node.Expanded = list[RestoreTreeViewIndex++];

            if (node.ChildNodes.Count > 0)

            {

                RestoreTreeViewExpandedState(node.ChildNodes, list);

            }

        }

    }

}

kick it on DotNetKicks.com   Thursday, January 19, 2006 10:05:42 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [31]  | 
 Friday, January 13, 2006

This little registry hack will put ActiveSync into the "Guest Only" mode. Once enabled, it will no longer form partnerships with connecting devices. You can still explore connected devices and install software.

At home, I sync my PocketPC directly with Exchange using Mobile ActiveSync over WiFi so there is no need for it to form a partnership with my desktop. At work, I have a steady supply of Symbol MC50s running across my desk and then out into the field. I don't want my email and contact information following them out the door. "Guest Only" fixes both of these issues.

REGEDIT4

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services]

"GuestOnly"=dword:00000001

I have seen this elsewhere but I can never find it when I need it.

Download the REG file:
http://download.binaryocean.com/GuestOnly.zip

 

kick it on DotNetKicks.com   Friday, January 13, 2006 2:30:19 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [1]  |