Wednesday, November 10, 2004

Today is a pretty exciting day - on a variety of levels.

First (and most importantly) I received my copy of Halo 2.  Now I realize that many enjoyed this thrill yesterday, but my patience has paid off.  The downside is I won't be able to play until later tonight (around 10:00 PM) but it's sitting here on my desk as a constant reminder that I have a date tonight.  I absolutely LOVE the Collector's Edition case - in particular the image on the back cover.  I'm pumped to play it; if you know me, you've known this for a while too ;-).

I'm not a hard-core gamer by trade - never really have been.  But despite the fact that I've owned Halo since I bought my XBox a few years ago, I hadn't passed the stinkin' game until just a couple of weeks ago in anticipation of being ready for part 2.  Now I'm ready!

Second, Mozilla released their very popular Firefox 1.0 browser today.  I've used their 0.9 version for some time as a 'testing' tool rather than my primary browser, but I've always been pleased with it.  Now, I'm not one to back down from my IE devotion.  I've enjoyed being able to take advantage of some of the IE-only extensions in order to create more fully featured, powerful browser-based web applications with great success.  That said, I'm pleased to find that much (but not all) of my code works as expected on this new browser.  I'll continue to use it, and I'd encourage you to do you same, but not as my primary browser - at least not yet.  However, IE 7 is long overdue; IE has been without any significant upgrades or enhancements (aside from the periodic security patch) far too long and I'd like to see something else, something exciting come out of Redmond on the browser front soon.

Hopefully, Firefox is an eye opener for the apparent complacent behavior on part of the MS team.

Wednesday, November 10, 2004 7:29:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Tuesday, November 09, 2004
Sorry if my blog has been acting up lately.  In making some modifications to it recently I erroneously left some invalid text in the web.config file.  I have since fixed it and things should be back to running order...thanks for your patience.
Tuesday, November 09, 2004 4:22:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Sunday, November 07, 2004

Though perhaps I'm not as affected as others I know by it, spam is a plague on the net.  I have had my share of garbage spam showing up in my blog and it's been pretty upsettings to find it there.

Today, I was browsing around a bit and found an anti-spam control that I am now fond of.  Miguel Jimenez has put together a small control and an Http Handler that provides a HIP (Human Interaction Proof) mechanism in the form of obfuscated text within an image.  When filling out a form the user must enter the text that appears in the image or else the submittal will not be accepted.

The installation was painless and I had it up an running in less than 2 minutes.  Basically it consists of added a .dll to your \bin, editing the web.config to register the Http Handler (the image generator), and add a pair of tags to the page on which you want to validate the submittal.  The two things that I wasn't really that excited about was 1) that the anti-spam control uses Session state so I had to enable it in the web.config where previously it was off and 2) sometimes the text can be quite difficult to read (e.g. discerning the difference between '$' and 's' can be quite difficult).

All in all, however, the process was seamless and I'm happy about the results.  Good job Miguel!

Sunday, November 07, 2004 6:10:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, November 05, 2004

Several months ago I wrote an article on enabling XP Visual Styles in your .NET 1.1 applications via a method called EnableVisualStyles().  This method, when coupled with a subsequent call to DoEvents() to work around a bug in the implementation of EnableVisualStyles() provided the nice, attractive Windows XP look and feel to which we've all grown accustomed.  If you fail to provide the DoEvents(), you will be greeted with an SEHException() that is not quite informative and can leave you scratching your head.

The alternative to this approach is to fall back to what was required in the good old days of .NET 1.0: that is, we must create a .manifest file.  Including the .manifest file along with your application is not very desirable.  A convenient, but painstaking remedy, is to embed the .manifest file xml directly into your executable post-build.  Simply open your executable in Visual Studio, add a new resource of the type RT_MANIFEST and paste your content.  Assign a resource id of 1 and change the Language to Neutral.  At this point you'd be good to go.  This process can be automated via code if you like as well.

These approaches are documented ad nauseum across the internet, so I won't consume any more time eating bandwidth on how they work (a simple Google search will provide all the answered you could want - and more).

One might ask, however, why on earth would I want to go through all the trouble of using a .manifest file (embedded or otherwise) when I have the option of using EnableVisualStyles()?  Well, the short answer is that EnableVisualStyles() doesn't fix the whole problem.  As it turns out, the issue resurfaced for me again this evening.

There is still an issue with respect to ComboBoxes and XP styles.  If you call a DoEvents() or show a dialog from a ComboBox event (such as KeyPress or SelectedIndexChanged) the SEHException will be thrown.  For example, consider the following code:

private void cboSearch_KeyPress(object sender, KeyPressEventArgs e) {
   if ( e.KeyChar == (char)Keys.Enter ) {
      e.Handled = true;
      doSearch();
   }
}

private void doSearch() {
   pnlStatus.Visible = true;
   Application.DoEvents();   // make sure the panel is fully visible before proceeding
   try {
      // ...search logic here...
   }
   finally {
      pnlStatus.Visible = false;
   }
}


The previous code will throw because of the call to DoEvents().  However, when a .manifest file is present this is a non-issue.

In fact, I think I'd be fine with the solution of using the .manifest exception for one BIG issue.  If your assembly is signed with a strong name (as mine is), you can't go changing the .exe file after it has been compiled.  Doing so will cause the runtime to throw a nasty “Strong name validation failed“ error message due to the fact that the checksums don't match up any more.  Upon seeing this error, I tried several solutions:

  • First, I created my own Win32 .res file in C++ with my .manifest file embedded as an RT_MANIFEST resource.  Then I wanted to add the .res file to my .csproj file but because of how .NET embeds resources that wouldn't work.
  • Second, I went to the command line to compile via csc.  The csc compiler accepts a switch /win32res that allows you to designate the .res file to embed within your assembly...this looked promising.  In fact it worked fine.  However, I have a solution of 5+ projects with 175+ files, several of which are forms that have .resx files associated with them...this complicates the build process as I do most of my compiling within the IDE.
    • I wish I could designate a .sln (or even a .csproj) file in the csc command line
    • ...looking forward to the MSBuild tool in Visual Studio 2005.

If you designate the /win32res switch on the csc commandline you will also experience an unfortunate pair of side effects:

  1. You trump VS's ability to create a VERSION resource based off of your Assembly attributes, so your .res file will need to include this if you want Explorer to show a 'Version' tab in the properties dialog for your executable and you'll have to maintain it manually versus allowing VS to update it.  Not to mention that VS adds some properties to the VERSION resource that aren't a part of the initial version block (such as Assembly Version).
  2. You cannot specify the /win32icon switch together with /win32res so you need to embed your app.ico file into your resource file properly, thereby eliminating VS's automatic generation of the Icon resource.

All in all it's a pain, and it's definitely not worth it...I'd rather distribute a .manifest file that have to deal with those headaches.

This exception was frustrating the first time I ran into the EnableVisualStyles() bug because I didn't know at first what was causing the problem.  It's even more frustrating & enfuriating now because I know that it's causing the problems and I can seemingly not do anything about it in code....or can I?

As it turns out, I can perform some magic...being the prestidigitator that I'd like to believe I am.  The remedy that I found, and yes, it is a sort of a hack, is to defer control to a Timer temporarily and have the timer invoke the call that has the DoEvents().  For example:

private void cboSearch_KeyPress(object sender, KeyPressEventArgs e) {
   if ( e.KeyChar == (char)Keys.Enter ) {
      e.Handled = true;
      tmrSearch.Interval = 10;   // make it quick so the user doesn't see any delay
      tmrSearch.Enabled = true;
   }
}

private void tmrSearch_Tick(object sender, EventArgs e) {
   // work around a bug in the ComboBox/EnableVisualStyles() with respect
   // to calling DoEvents from within a ComboBox event.
   tmrSearch.Enabled = false;   // only allow the event to run once
   doSearch();
}

private void doSearch() {
   pnlStatus.Visible = true;
   Application.DoEvents();   // make sure the panel is fully visible before proceeding
   try {
      // ...search logic here...
   }
   finally {
      pnlStatus.Visible = false;
   }
}


So there seems to be a remedy in code, but I can't say that I really recommend it as a best practice.  The best way (i.e. the least error prone) is to go the route of the .manifest file, but it's not without its complications and gotchas.  I would much prefer to use the EnableVisualStyles(), and now that I know of a way to work around the issues until fixed I can live with it.

Friday, November 05, 2004 8:29:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Monday, November 01, 2004

If you're like me in your GDI+ adventures you've run across the Image.GetThumbnailImage(...) method and been disappointed with its results.  This method opts for performance over quality when rendering your thumbnail image and as a result your thumbnails can look discolored or distorted.  I wanted to have a routine that provided a high performance alternative but would render a better quality image.

The way I implemented this at first was to iterate through the pixels of the source image, performing averages of pixel color over an area of pixels, and writing that resultant pixel to the output (thumbnail) image.  I wrote this a couple of years ago and it did the trick nicely and for a small number of small pictures it was more than adequate; with larger pictures, on the other hand, the performance degradation was noticeable.  I've attached the code for your viewing pleasure:

public static Bitmap CreateThumbnail(Bitmap source, int thumbWi, int thumbHi, IProgress progressCallback) {
   if ( thumbWi > source.Width || thumbHi > source.Height ) return null;

   Bitmap ret = new Bitmap(thumbWi, thumbHi);
  
   float xScale = (float)thumbWi / ((float)source.Width - 1);
   float yScale = (float)thumbHi / ((float)source.Height - 1);

   for ( int i = 0; i < thumbHi; i++ ) {
      for ( int j = 0; j < thumbWi; j++ ) {
         int x1 = (int)( j / xScale );
         int x2 = (int)( ( ( j + 1 ) / xScale ) - 1 );
         int y1 = (int)( i / yScale );
         int y2 = (int)( ( ( i + 1 ) / yScale ) - 1 );
         float r = 0, g = 0, b = 0;
         for ( int x = x1; x <= x2; x++ )
            for ( int y = y1; y <= y2; y++ ) {
               int c = source.GetPixel(x, y).ToArgb();
               r += ( c & 0xff0000 ) / 0xff01;
               g += ( c & 0xff00 ) / 256;
               b += ( c & 0xff );
            }

         int numPixels = ( x2 - x1 + 1 ) * ( y2 - y1 + 1 );
         ret.SetPixel(j, i, Color.FromArgb((int)( r/numPixels ), (int)( g/numPixels ), (int)( b/numPixels )));
      }

      if ( null != progressCallback ) progressCallback.Report(i / thumbHi * 100);
   }

   return ret;
}


Recently, however, it became important to have a faster algorithm to generate image thumbnails.  To meet these new demands, I produced the following code which results in as good a thumbnail as my previous code but MUCH faster - though not quite as fast as the GetThumbnailImage(...) method.  Here is its code:

public static Bitmap CreateThumbnail(Bitmap source, int thumbWi, int thumbHi) {
   // return the source image if it's smaller than the designated thumbnail
   if ( source.Width < thumbWi && source.Height < thumbHi ) return source;

   System.Drawing.Bitmap ret = null;
   try {
      int wi, hi;

      // maintain the aspect ratio despite the thumbnail size parameters
      if ( source.Width > source.Height ) {
         wi = thumbWi;
         hi = (int)(source.Height * ((decimal)thumbWi / source.Width));
      }
      else {
         hi = thumbHi;
         wi = (int)(source.Width * ((decimal)thumbHi / source.Height));
      }

      // original code that creates lousy thumbnails
      // System.Drawing.Image ret = source.GetThumbnailImage(wi,hi,null,IntPtr.Zero);
      ret = new Bitmap(wi, hi);
      using ( Graphics g = Graphics.FromImage(ret) ) {
         g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
         g.FillRectangle(Brushes.White, 0, 0, wi, hi);
         g.DrawImage(source, 0, 0, wi, hi);
      }
   }
   catch {
      ret = null;
   }

   return ret;
}


Enjoy!...and happy thumbnailing!

Monday, November 01, 2004 9:05:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [7]  |  Trackback

In developing pages and controls in ASP.NET I've come across situations in which I need to bind against properties that are not implemented on the default interface of the object in question.  For the most part, this is really never an issue.  Typically you have an object (be it a user-defined class instance, or something more data-centric such as a DataSet or a DataReader) and you want to bind against it.  Your syntax might frequently resemble the following:

<%# DataBinder.Eval(Container.DataItem, "UserName") %>


where this code will evaluate (via Reflection) the item being bound (identified by Container.DataItem) and extract the value contained within the UserName property/column/etc.  This is all well and good and usually all that you need.  However, only properties (and methods) on the default interface are sought.  That is, if your object (Container.DataItem) implements and interface and maps to the interface methods directly rather than implementing them generically by name, the runtime will not be able to resolve to them.

For example, suppose you have an IUser interface defined and implemented within a User class:

public interface IUser {
   string UserName { get; set; }
}

public sealed class User : IUser {
   private string _userName;

   public string UserName {
      get { return _userName; }
      set { _userName = value; }
   }
}


In this scenario, your databinding would work perfectly.  Yes, UserName maps to the IUser.UserName property implicitly, but is also defined on the default interface for User.  Suppose, however, that the implementation were explicit:

public sealed class User : IUser {
   private string _userName;

   string IUser.UserName {
      get { return _userName; }
      set { _userName = value; }
   }
}


Now, the databinding would fail because there is no property called UserName on the default interface of the User class.  In this circumstance, it is important to take matters into our own hands and perform the casting on the ASP.NET page/control ourselves.  This may also require that we fully qualify the interface name (using the proper namespace) or use an <%@ Import namespace="..." %>directive.

<%@ Import namespace="..." %>

<%# ((IUser)Container.DataItem).UserName %>


There, works like a charm.  Note, that depending on the content of the property, you might be best served by enclosing the operation in a Server.HtmlEncode() function call to prevent any misuse, XSS (Cross Site Scripting), or HTML/Script injection.

Monday, November 01, 2004 3:25:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, October 28, 2004

I'm liking this.  I found a new tool called PostXING, by Christopher Frazier while reading through a blog post by Darren Neimke.  It's pretty slick.  I especially like the fact that there is a Design View, HTML view, and a Preview option.  It's been a pain to perform syntax hilighting in the past - I've resorted to manual highlighting as well as some other strategies.

This product is very nice.  Its ability to post pictures is very handy as well as there is no such support natively in .Text.  While I have no immediate need for the cross site posting, I can see that to be a very handy feature and may end up using it in the not-so-distant future.

There are a couple of loose ends:

  • Font sizes on the FTP settings tab are a bit too large that they wrap
  • The auto-resizing of the controls on the Syntax Highlighting form needs addressing
  • I'm unclear on the Url textbox and what it's purpose is
  • Post vs. Post & Publish?

Aside from these minor issues, I really enjoy it.  Thanks Christopher for a job well done!

BTW: This post was made courtesy of the PostXING product :-)

Thursday, October 28, 2004 4:19:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Tuesday, October 26, 2004

[Updated 10/29/2004 with item #6]

I figured that for my 100th post I'd put something out there that I hope to get lots of feedback on.

Each day as I'm coding I invariably stumble across a language feature that just doesn't sit right with me.  That, or I get to thinking, I wish the BCL's supported X function or Y capability.  While I'm not coding, however, I tend to forget these items until I once again go crashing headfirst up against it.

I've given this some thought, but will probably be amending it a bit here in the next few days as I expect I'll encounter a few more.  So, without further ado, here's my .NET wish list (NOTE: I'm not addressing several issues that I know will be fixed within Whidbey such as scoped accessors on properties, etc):

1. CONSTANTS

I really wish I could declare globals (public constants) at the namespace level without having to resort to an enumeration or a class when the values aren't conceptually enumerated or non-integers.  I'd love the ability to create public and/or internal constants like this:

namespace SomeNamespace {
   internal const int MaxIdLength = 15;
  
   public class Employee {
      public const int MaxNameLength = MaxIdLength;
      // ... class code here ...
   }
}


1a. DEFINES

Along the same lines as constants, having the ability to perform a #define would be very powerful.  Where a constant can potentially be exposed outside the library as a value, a #define only has applicability to the compiler preprocessor.

#define S_RES_APPLICATION_TITLE 10001

namespace SomeNamespace {

   internal sealed class Res {
      internal static string GetString(int id) {
         // return the designated resource value
      }
   }
 
   internal sealed class EntryPoint {
      public static void Main() {
         System.Windows.Forms.MessageBox.Show(Res.GetString(S_RES_APPLICATION_TITLE));
      }
   }
  
}


Now there might be some issues of type safety here that would need to be addressed, but this capability would be extremely enabling and powerful...hearkening to what C++ developers can already do.

2. TRY..CATCH..FINALLY VARIABLES

I am of the firm belief that if a variable is declared within the try block its scope should extend to both the catch and the finally blocks.  As it stands, in order to use a variable in the various blocks you must declare it outside the try..catch..finally.  In other words, if I declare a SqlConnection within a try I can't Dispose() of it in the finally...I must declare it before the try.  This can lead to poor code.  First of all, the object's scope now extends beyond its intended usage, a bad practice as far as I'm concerned.  This would be ideal:

public string GetName(int id) {
   try {
      SqlConnection cn = new SqlConnection("...");
      // get the name and return it
   }
   finally {
      if ( null != cn ) cn.Dispose();
   }
}


There might very well be some technical reasons behind why this is so danged difficult, but I believe it would lead to much clearer code and the developer's intentions would be more easily maintained.

3.  SCOPED INHERITANCE

I get fed up with having to scope my base classes the same as the deriving classes (or vice versa).  Oftentimes, I am wanting to declare a base class to be internal to my assembly, but have a public class that derives from it.  I am using the base class internally for private functionality and object organization, but I don't need it exposed.  Yes, I know I can probably use an internal interface and a private class to accomplish something similar, but that's not what I want to do.

If in fact I do have to expose the base class (which I might be amenable to), I'd at least like to have it internally abstract and publically sealed.

Ideally:

internal abstract Base {
   // ... some methods here ...
}

// here sealed would be implied by virtue of the fact that the
// abstract base class is not publically exposed

public class Derived : Base {
   // ... implementation ...
}


Willing to Accept:

public sealed internal abstract Base {   // or something like that
   // ... some methods here ...
}


Or even:

internal abstract Base {
   // ... some methods here ...
}

public sealed class Derived : internal Base {
   // ... implementation ...
}


4.  STRING.ZERO()

In an effort to provide more out of the box security, I believe the String class should provide a .Zero() method.  This method would be a void method, but when called would zero out/blank out the contents within the string.  I'd imagine that internally it would call SecureZeroMemory().

Yes, we could probably accomplish this using unsafe methods, but that's not a recommended/supported route.  Instead support for this should be built into the framework.

string pwd = txtPassword.Text;
// of course this would have been acquired encrypted and/or securely
// ... use the password variable to login, access a resource, etc
// now that we're done with it, clear it out
pwd.Zero();

This could potentially have further reaching impacts; it could adversely affect parameters, etc, but would provide a nice mechanism to blank out information that you don't want dangling in memory when you're done with it.

5. INDEXERS

It's pretty darned convenient to be able to add an indexer to your class.  It would be very powerful to have this functionality extended to support indexers on properties rather than just on this.  This capability would enable a more flexible and powerful mechanism for indexing into collections internal to your classes without having to write accessors that don't exhibit an indexing mechanism via [].

public sealed class Quote {

   private QuoteLineItem[] _lineItems;
  
   public QuoteLineItem LineItem[int i] {
      get { return _lineItems[i]; }
   }
}


6. NOITEMSTEMPLATE

This is pretty esoteric, but since day 1 that I got into .NET development this one has bugged me and I just remembered it today.  The ASP.NET Data(Grid|List) and Repeater controls have some niceties and are pretty powerful controls.  Each of these controls allows you to define templates for how records are rendered in the browser via the <itemTemplate>.  But what if your controls is being bound to a data source that doesn't have any records?

In this case you have to perform custom server logic and then determine the proper course of action or your content is going to look horrible in the browser.  I think there should be a <noItemsTemplate> that allows you to specify what should render on the browser in the even no items were bound.  This would return control back to the UI designers to lay out the page as they see fit.

<asp:Repeater id=rpt runat=server>
   <noItemsTemplate>
      We're sorry, there are no employees that match your query.
   </noItemsTemplate>
   ...
</asp:Repeater>

Tuesday, October 26, 2004 5:34:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback