Wednesday, December 1, 2010

Changing the opacity of an Image (.NET C#)

Setting up the opacity of an Image is very useful and reasonably easy to to. In my Card Maker application I needed to load a bitmap, set the opacity, and make sure the image file was not locked(!).

The critical piece is the configuration of the Matrix33 value. This configures the alpha component of the matrix. (a value from 0 to 1 in my sample)

It is important to call Dispose on loaded images files that are no longer needed. This is critical to avoid locking the file (and angering you and your application users).

ColorMatrix zColor = new ColorMatrix();
zColor.Matrix33 = (float)opacity / 255.0f;
ImageAttributes zAttrib = new ImageAttributes();
Bitmap zSourceImage = new Bitmap(sFile);
Bitmap zBitmap = new Bitmap(zSourceImage.Width, zSourceImage.Height); // target image
Graphics zGraphics = Graphics.FromImage(zBitmap);
// draw the source image into the destination with the desired opacity
zGraphics.DrawImage(zSourceImage, new Rectangle(0, 0, zBitmap.Width, zBitmap.Height), 
0, 0, zBitmap.Width, zBitmap.Height, GraphicsUnit.Pixel, zAttrib);

Monday, November 29, 2010

Named Pipes (.NET C#)

Named pipes can be very useful for a variety of functions. I found that a named pipe was the right solution for passing the command line arguments to an already running application (avoiding reloading the application entirely). NamedPipeServerStream and NamedPipeClientStream are the basic classes necessary to create a byte stream pipe between various applications.

A named pipe is a single connection utility. If you make a connection and disconnect you will need to create a new one. You have a few options on how to handle multiple connections with multiple threads. I simply setup a while loop that continued to recreate the named pipe as connections were made and closed. I am sure I still have a lot more to learn about using pipes.

// Server Side
NamedPipeServerStream zPipe = new NamedPipeServerStream(PIPE_NAME, PipeDirection.In, 1, PipeTransmissionMode.Message);
StringBuilder zBuilder = new StringBuilder();
    int nLength = zPipe.Read(arrayData, 0, arrayData.Length);
zBuilder.Append(Encoding.UTF8.GetString(arrayData, 0, nLength));
} while (!zPipe.IsMessageComplete);
// Client Side
NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", PIPE_NAME, PipeDirection.Out);
catch (Exception) {return;}
if (pipeClient.IsConnected && pipeClient.CanWrite)
    byte[] arrayData = Encoding.UTF8.GetBytes(sMessage);
pipeClient.Write(arrayData, 0, arrayData.Length);

Server Pipe
Client Pipe

My previous experience with byte reading and writing to Sockets helped me understand the basics of a pipe. If you have written to streams of any sort you should be able to figure out pipes.

Tuesday, November 16, 2010

ScrollToControl (.NET C#)

If you are using a Panel you may notice that it jumps around when you restore focus. It is actually jumping to the xy position of the current control within the Panel. This is due to implementation calling ScrollToControl. For example I have an application that uses a Panel as a convenient alternative to creating a ScrollableControl. My control is the only one in the Panel and I wanted to take advantage of the background image along with the auto-scroll functionality. My Panel is a specialized derivative of Panel so I went ahead and created the override below:

   1:  protected override Point ScrollToControl(Control activeControl)
   2:  {
   3:      if (m_bDisableScrollToControl)
   4:      {
   5:      return AutoScrollPosition;
   6:      }
   7:      return base.ScrollToControl(activeControl);
   8:  }

Basically I only allow the ScrollToControl if my custom boolean is enabled. In the case of a single control it will likely never be enabled. Instead I just leave the position as-is based on the AutoScrollPosition.

Friday, November 5, 2010

Saving & Loading a Form's state (.NET C#)

Saving and loading the state of a window is a very much appreciated (and often overlooked) feature of an application. There is a slight trick to it though. It is not apparent unless you dig a bit. Based on the state of the Form the Location and Size are not what you expect. If a window is anything but FormWindowState.Normal the Size and Location are not the values you want to save. Instead you need to store the RestoreBounds values of those fields. I have an example implementation below for storing the state of a Form to a string followed by the code to restore it.

   1:  public static string GetFormSettings(Form zForm)
   2:  {
   3:      if (FormWindowState.Normal == zForm.WindowState)
   4:      {
   5:          return zForm.Location.X + ";" + zForm.Location.Y + ";" +
   6:              zForm.Size.Width + ";" + zForm.Size.Height + ";" +
   7:              (int)zForm.WindowState;
   8:      }
   9:      else
  10:      {
  11:          return zForm.RestoreBounds.Location.X + ";" + zForm.RestoreBounds.Location.Y + ";" +
  12:              zForm.RestoreBounds.Size.Width + ";" + zForm.RestoreBounds.Size.Height + ";" +
  13:              (int)zForm.WindowState;
  14:      }
  15:  }
  17:  public static void RestoreState(Form zForm, string sInput)
  18:  {
  19:      string[] arraySplit = sInput.Split(new char[] { ';' });
  20:      int[] nValues = new int[5];
  21:      if (5 == arraySplit.Length)
  22:      {
  23:          for (int nIdx = 0; nIdx < arraySplit.Length; nIdx++)
  24:          {
  25:              nValues[nIdx] = int.Parse(arraySplit[nIdx]);
  26:          }
  27:          zForm.Location = new Point(nValues[0], nValues[1]);
  28:          zForm.Size = new Size(nValues[2], nValues[3]);
  29:          zForm.WindowState = (FormWindowState)nValues[4];
  30:      }
  31:  }

MSDN Forms.RestoreBounds

Thursday, November 4, 2010

Dictionary vs. Enum.Parse (.NET C#)

I have often wondered if I should use Enum.Parse or a Dictionary of strings to translation a string to an enumeration value. I have always suspected the Dictionary look up would be faster than the Enum.Parse. I decided it was time to test things out. Here's the sample code:

   1:  enum Place
   2:  {
   3:      Home,
   4:      Work,
   5:      Neither,
   6:      End = Neither
   7:  }
   9:  static Dictionary<string, Place> dictionaryPlaces = null; 
  11:  static void Main(string[] args)
  12:  {
  13:      const string sHome = "Home";
  14:      const string sWork = "Work";
  15:      const string sNeither = "Neither";
  16:      const string sEnd = "End";
  18:      if (!Stopwatch.IsHighResolution) { throw new Exception("No high resolution timer! :("); }
  19:      Stopwatch zStopwatch = Stopwatch.StartNew();           
  20:      dictionaryPlaces = new Dictionary<string, Place>();
  21:      dictionaryPlaces.Add(sHome, Place.Home);
  22:      dictionaryPlaces.Add(sWork, Place.Work);
  23:      dictionaryPlaces.Add(sNeither, Place.Neither);
  24:      dictionaryPlaces.Add(sEnd, Place.End);
  25:      zStopwatch.Stop();
  26:      Console.WriteLine("Dictionary Creation: " + zStopwatch.ElapsedTicks);
  28:      for (int nIdx = 0; nIdx < 2; nIdx++)
  29:      {
  30:      Console.WriteLine(Environment.NewLine + "--Dictionary Lookup");
  31:      LookupEnumByDictionary(sHome);
  32:      LookupEnumByDictionary(sWork);
  33:      LookupEnumByDictionary(sNeither);
  34:      LookupEnumByDictionary(sEnd);
  36:      Console.WriteLine(Environment.NewLine + "--Enum Lookup");
  37:      LookupEnum(sHome);
  38:      LookupEnum(sWork);
  39:      LookupEnum(sNeither);
  40:      LookupEnum(sEnd);
  41:      }
  42:      Console.ReadLine();
  43:  }
  45:  static void LookupEnumByDictionary(string sValue)
  46:  {
  47:      Stopwatch zStopwatch = Stopwatch.StartNew();
  48:      Place ePlace = dictionaryPlaces[sValue];
  49:      zStopwatch.Stop();
  50:      Console.WriteLine(ePlace.ToString() + "(" + zStopwatch.ElapsedTicks + ")");
  51:  }
  53:  static void LookupEnum(string sValue)
  54:  {
  55:      Stopwatch zStopwatch = Stopwatch.StartNew();
  56:      Place ePlace = (Place)Enum.Parse(typeof(Place), sValue);
  57:      zStopwatch.Stop();
  58:      Console.WriteLine(ePlace.ToString() + "(" + zStopwatch.ElapsedTicks + ")");
  59:  }

Here's the output:

Dictionary Creation: 15315
--Dictionary Lookup
--Enum Lookup
--Dictionary Lookup
--Enum Lookup

The initial hits of the Dictionary construction and initial query are large but if you have a program performing a lot of string to enumeration values the Dictionary would result in the best performance over time. I added the second pass through the loop as I guessed it might further reveal the likely pattern.

Wednesday, November 3, 2010

RSACryptoServiceProvider (.NET C#)

Long ago I wrote a file server that provided encrypted passwords at login. To encrypt the passwords I used RSACryptoServiceProvider. It is a reasonably simple way to generate a public and private key so you can encrypt information and pass it back and forth. The code below passes a new public key (RSAParameters) to the client in the form of an XML serialized object. The code missing in this example is the actual Socket interaction back and forth. The server side also has an RSA.Decrypt call later used to check the validity of the sent password.

   1:  // Server Side
   2:  RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
   3:  RSAParameters zParams = RSA.ExportParameters(false); // false avoids exporting the private key!
   4:  MemoryStream zStream = new MemoryStream();
   5:  XmlSerializer zXSerial  = new XmlSerializer(zParams.GetType());
   6:  zXSerial.Serialize(zStream, zParams);
   7:  // send public key to client
   8:  ...
   9:  // decrypt and check password
  12:  // Client Side
  13:  RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
  14:  RSAParameters zParams = new RSAParameters();
  15:  XmlSerializer zXSerial = new XmlSerializer(zParams.GetType());
  16:  MemoryStream zStream = new MemoryStream(arrayPostHeader);
  17:  zStream.Seek(0, SeekOrigin.Begin);
  18:  zParams = (RSAParameters)zXSerial.Deserialize(zStream);
  19:  RSA.ImportParameters(zParams);
  20:  arrayEncrypted = RSA.Encrypt(m_zEncoder.GetBytes(sPassword), false);
  21:  // send to server
(line 16) arrayPostHeader is a byte[] related to the Socket message to be sent back to the server
(line 20) arrayEncrypted is a byte[] and sPassword is a string

I recall being very glad that encryption was simple to setup and use!

Looking  back at my old code I can see that line 15 really should just be a typeof. There's really no need to create a new object if you just need the type.

Tuesday, November 2, 2010

ListBox Item Text Update (.NET C#)

ListBoxes are a convenient control that allows you toss any object into it and display the list of items to the user. You can override the ToString method to display your object name as you see fit. Unfortunately you cannot update the name of an item in the list by changing the variables related to your ToString override. I have seen a number of interesting approaches to the problem online. I created one of my own as it seemed like it might work. It looks a bit odd... but the reassignment of an item to itself triggers the necessary update to your text.

listBoxFiles.Items[listBoxFiles.SelectedIndex] = listBoxFiles.Items[listBoxFiles.SelectedIndex];

This is "uh" solution to the problem. I do not recommend it wholesale. It will work well if your ListBox is single selection and not sorted(see below on those). You should also evaluate the alternatives out in google land or wherever you find interesting solutions to annoying problems (back alleys, bingo parlors, or a bottle of alcohol). Plus you may run into some extra fun in the following situations:

Sorted ListBox
  • You are not "adding" items to the list box, just changing the array of items. You will need to set Sorted to false then true to trigger a proper sort.
  • ...and more... ?
  • Your selection will need to be carefully managed. The reassignment of multiple items in the array will likely break your selection state at the conclusion of the rename.
  • ...and more... ?

Monday, November 1, 2010

Clean your PC!

This past Saturday I was coding and my computer shut off on its own. It proceeded to shut down a number of times throughout the morning before I finally broke out my vacuum. I took out my nVidia GTX 260 video card to clean it and found a nice healthy layer of dust. I gave everything a decent cleaning and put everything back together. When I powered my PC up the video card was running 10 degrees (Celsius) cooler! I also found that my highest temperature from running a game (Dead Space in this case) was 15 degrees cooler. (around 55)

I've often heard and recommended "reboot your pc" as the obvious answer to most problems. Now I will add "vacuum or blow out the dust in your pc" to my list of simple recommendations when strange things come up.

Friday, October 29, 2010 (Action Script 3.x)

I recently had the chance to work in Action Script at my job. I had not worked in Action Script previously but was encouraged as the language is a mix of JavaScript and C#/Java (two languages I am reasonably comfortable with). One of the tasks I tackled was backing up data to the hard drive using FileReference. FileReference is a simple way to access the file save and load functionality within a browser or otherwise. I was able to do some fairly neat things such as serializing objects and saving/loading them in a binary file. Writing XML to a file was simple. Action Script has a good amount of XML processing functionality (although sometimes a bit confusing to someone new to it) so reading the file back in was no problem. FileReference takes care of the save/load dialog and works with callbacks. It is clearly geared towards pushing the developer to make a decent user interface that doesn't lock up the render thread. (many developers don't seem to care about this kind of thing!)

FileReference (Adobe livedocs)

Thursday, October 28, 2010

Graphics.DrawString vs. Path.AddString

In my Card Maker application I recently added support for drawing elements / text with an outline. Unfortunately in doing so I ran into a major difference in the scale at which Graphics.DrawString and Path.AddString draw. The scale of the font drawn by Graphics.DrawString is about 4/3 the size of one drawn by Path.Addstring

(... removed old terrible solution ...)

My original solution to the problem was a hack using a magic value. You should be looking at the Font.Unit and checking if it is GraphicsUnit.Point. If so then should be converting the font size to the EM size like so:

Graphics.DpiY * (zFont.Size / 72f)
If the Font.Unit is another value you should research further. Thanks to Mike Garrett for his comment. The documentation for the GraphicsUnit.Point (and other values) on MSDN reveals some of the mystery.

Wednesday, October 27, 2010

Dictionary (.NET C#)

The System.Collections.Generic.Dictionary is incredibly easy to use. It helped me clean up some of the most excessive casting in my history as a coder. My early days of Java and C# had a lot of terrible looking code with lots of mystical casts on objects pulled from Hashtables. The haphazard casting of objects is not exactly desirable. It is a necessary evil at times, but clearly known key and value types in a Hashtable type data structure should not be one of those necessary evils.

Bitmap zBitmap = null;
string sKey = sFile.ToLower();
if (s_htImages.ContainsKey(sKey))
  zBitmap = (Bitmap)s_htImages[sKey];

Tuesday, October 26, 2010

Graphics.MeasureString (.NET C#)

After testing out various situations for scaling the font of a string to fit the text within a given Rectangle I finally settled on Graphics.MeasureString. There is a cpu hit to performing the measurement, but if you can limit the number of times you need measure it is worth it. The code below is from my Card Maker application. It handles adjusting the font size based on the size of the target Rectangle.

SizeF zSize = zGraphics.MeasureString(sInput, zFont, new SizeF(zElement.width, int.MaxValue), zFormat);
if (zSize.Height > zElement.height || zSize.Width > zElement.width)
  float newSizeRatio = 1f;
  if ((zSize.Height - zElement.height) > (zSize.Width - zElement.width))
    newSizeRatio = (float)zElement.height / (float)zSize.Height;
    newSizeRatio = (float)zElement.width / (float)zSize.Width;
  Font scaledFont = new Font(zFont.FontFamily, newSizeRatio * zFont.Size, zFont.Style);
  zFont = scaledFont;

  • zElement is an object containing the target width and height.
  • The ratio can differ due to the need to keep the text within the Rectangle. Drawing outside of the target Rectangle would defeat the purpose!
  • The int.MaxValue may seem strange but the height of the allowed Rectangle (to measure within) is not important to me. The text being tested by MeasureString is formatted to line wrap.

Monday, October 25, 2010

TryParse (.NET C#)

Back in the old days of .NET 1.x it was common to have this sort of code to convert a string into an int variable:

int x = 0;
x = int.Parse("bad");
catch (Exception)

While the code above was effective it required a try catch to handle errors. As of .NET 2.x there is a TryParse method in addition to the original Parse method on a variety of types. The code is a lot simpler. The return value of TryParse is a bool so your code can be a little less messy. Wrapping things in an if statement is a lot better than a try/catch for a variety of reasons.

int x = 0;
int.TryParse("bad", out x);

MSDN Int32.TryParse

Friday, October 22, 2010

XSD.exe (.NET)

To me XSD.exe is a tool for generating a code file for representing code accessible XML data. There are a variety of other uses but that is the one I have actually setup in projects. The generated code is also setup in a partial class so it is easy to expand upon the functionality of a given XSD based object. I generally build my XSD schema file and then use the pre-build event to invoke XSD.exe to generate the code file representing my objects. While XSD.exe/generated code usage may not always be the most appropriate, especially if your schema is not set in stone... It is a powerful tool to have accessible objects from XML with minimal setup time.

MSDN XSD (VS 2005)

Thursday, October 21, 2010

PropertyGrid (.NET C#)

The topic today is simply the PropertyGrid. While to many this is nothing new nor very exciting. But if you have been writing applications without knowledge of the PropertyGrid control now is the time. Go forth and investigate. The PropertyGrid allows you to assign an object and not only view but edit the properties of an object. It makes debugging and tweaking incredibly easy. There are some disadvantages though. You cannot cycle through values, instead you must commit each change by pressing enter or leaving the control. Below is an example of a property exposed from an object with just the bare essential properties. The description to display in the PropertyGrid for the Thickness property is defined with the DescriptionAttribute.

[DescriptionAttribute("Border Thickness (0 is fill)")]
public int Thickness
get { return m_nThickness; }
set { m_nThickness = value; }

You will need to do a little research on the various attributes you can apply to your properties. Some basics are: 
  • CategoryAttribute
  • DescriptionAttribute 
  • BrowsableAttribute 
  • ReadOnlyAttribute 
  • DefaultValueAttribute 
  • DefaultPropertyAttribute
To assign an object for viewing/editing just assign your PropertyGrid.SelectedObject value the desired object. There are of course events associated with the PropertyGrid as well so you can catch value changes. The only application I have used a PropertyGrid for so far is my Card Maker application. I will definitely consider it in any future projects or those I revisit.

Wednesday, October 20, 2010

Drawing Text with Ellipsis (.NET C#)

Although I have not used it extensively, the StringFormat.Trimming functionality could come in handy in many situations. This will change the way Graphics.DrawString renders text within the destination rectangle. You can specify a visual indicator to the user that the text contents are larger than the rectangle it is being drawn within. Based on the StringFormat.Trimming setting the behavior will differ.

StringFormat stringFormat = new StringFormat();
stringFormat.Trimming = StringTrimming.Character;
stringFormat.Trimming = StringTrimming.EllipsisCharacter;
stringFormat.Trimming = StringTrimming.EllipsisPath;
stringFormat.Trimming = StringTrimming.EllipsisWord;
stringFormat.Trimming = StringTrimming.None;
stringFormat.Trimming = StringTrimming.Word;
(Note: The above is just a list of possible settings... please do not write code like this ever)
Unfortunately there is no indication, other than the obvious visual, that a string was truncated. I am still investigating solutions to determine if the text will be cut off by the destination rectangle. Graphics.MeasureString is far from fast and Graphics.MeasureCharacterRanges seems to be a bit of a mystery thus far. This will likely become a later topic unless I just forget about it...

Tuesday, October 19, 2010

ScrollableControl and Panel: Mouse Scroll and Draw (.NET C#)

The ScrollableControl class is great if you are creating a control that will need to display the scroll bars vertically and horizontally. The Panel control does the same with the controls added to it. Unfortunately, by default, when you drag the scroll bar with the mouse the rest of the control does not draw until you let up on the mouse button. In every application I have created I have never wanted this behavior. I finally took some time to investigate and found 1 magical line of code. Followed up by 5 further magical lines of code.

SetScrollState(ScrollableControl.ScrollStateFullDrag, true);
public static void SetupScrollState(ScrollableControl scrollableControl)
 Type scrollableControlType = typeof(ScrollableControl);
 MethodInfo setScrollStateMethod = scrollableControlType.GetMethod("SetScrollState", BindingFlags.NonPublic | BindingFlags.Instance);
 setScrollStateMethod.Invoke(scrollableControl, new object[] { ScrollableControl.ScrollStateFullDrag, true });

SetScrollState on MSDN
ScrollStateFullDrag on MSDN

By enabling the ScrollStateFullDrag your control will hit the OnPaint event each time the scroll value changes. Though beware... there is one minor issue I ran into. The state of the flag appears to be reset each time the size of the scrollable control changes. In my case each time I changed the AutoScrollMinSize I just called SetScrollState again.

The second block of code (the SetupScrollState method) is a bit more back door approach to setting up the ScrollStateFullDrag on your ScrollableControls. I found a good post by someone by the nickname dpuza (forum link) indicating an approach by which to call the protected SetScrollState method in your ScrollableControl. It works well, though you may feel a bit wrong making the reflection call... This is one approach to setup your existing Panel control to draw and scroll without creating a new PanelEx type of class.

Monday, October 18, 2010

User Controls: Double Buffering (.NET C#)

I figured I would jump right into things... but it is my first post so I figure I should explain the subject matter. This blog is dedicated to things I have learned while coding. I am primarily a C# programmer that is slightly behind the times. I am still enjoying .NET 2.x.

Now on to the topic of the day: Double Buffering User Controls

I had an old block of code to copy-and-paste around that performed double buffering manually. It created a back buffer to draw into and improved the problems with flickering in my applications. It worked reasonably well. Fortunately my old block of code was made obsolete by 4 lines of very powerful code. (it could be 1 with ORs)

   1:  SetStyle(ControlStyles.AllPaintingInWmPaint, true);
   2:  SetStyle(ControlStyles.UserPaint, true);
   3:  SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
   4:  SetStyle(ControlStyles.Opaque, true);

ControlStyles Enumeration at MSDN

  • AllPaintingInWmPaint and OptimizedDoubleBuffer are actually required together based on the documentation. 
  • Opaque eliminates any background drawing. Depending on your application you may want a background.
  • UserPaint turns over paint responsibility to the control.
The performance actually improved quite significantly over the old manual double buffering. Plus my code is much simpler and ever-so-slightly more logical.