Getting a stream to a resource without copying the contents into memory

David Anderson recently responded to a question I asked on stackoverflow regarding how to access binary resources in a .resx file as a Stream rather than a byte[] (which ResourceManager exposes by default). It goes into detail about how ResourceManager always copies the data into memory, and how to use manifest resource streams to overcome this problem:

Getting a stream to a resource without copying the contents into memory on David Anderson’s blog

XML Serialisation and System.Drawing.Color

Background

I’m currently doing some work in the area of cross-AppDomain development, where all objects are either marshalled (transparently) using .NET Remoting or serialised. It turns out that, when DataSet objects are serialised, their extended properties are serialised as strings. This means that, when operating on a DataSet which has come from another AppDomain, the complex data type you added as an extended property has unexpectedly become a string representation of it.

There’s a quick and easy solution to this problem; manually serialising extended properties using the built-in .NET XML serialisation mechanism. However, not all .NET types are fully supported by the XML serialiser, as I discovered while trying to serialise an object with a property of type System.Drawing.Color. Here’s a quick and easy way to work around this issue:

Solution

The solution is two-fold; firstly, we should exclude the Color property from XML serialisation (using the XmlIgnore attribute), because we know it’s not supported:

[XmlIgnore]
public Color TextColor {
    get;
    set;
}

Next, we need to provide an additional public read/write property that is XML-serialisable:

public string TextColorHtml {
    get { return ColorTranslator.ToHtml(TextColor); }
    set { TextColor = ColorTranslator.FromHtml(value); }
}

The property needs to be public and provide a getter and setter, because the XML serialiser will invoke it, and does not execute with high enough privileges to be able to read into private/protected/internal properties or set the values of backing variables. I’ve chosen to serialise the HTML representation of the colour, because it is already XML-friendly and translates back and forth easily.

The advantage to using this approach is that you do not have to change the representation used by your class; the Color structure is very useful and very pervasive in .NET. Also, since the additional property has no backing variable (it is entirely procedural), no additional memory is needed to store each instance of the type.

Drop-Down Controls Revisited

From time to time, it’s a good idea to go back and re-examine old code. With time comes greater knowledge and new tricks; and in the case of two of my earlier custom Windows Forms controls, this was certainly true. You may remember my ComboBox control with grouping support, as well as my ComboBox with a TreeView drop-down – I have revisited these controls, with particular mind to implementing what I learnt from my experience with the Buffered Paint API.

New versions of GroupedComboBox and ComboTreeBoxGroupedComboBox

To refresh your memory, this control extends ComboBox and adds a new property; GroupMember. Using PropertyDescriptor and owner-drawing, it groups together items whose grouping values are equal.

What’s new:

  • On Windows Vista and 7, the control did not appear in the ‘button style’ consistent with normal ComboBox controls in DropDownList mode; this is a limitation of owner-drawing, but one that can be overcome through the use of VisualStyleRenderer. This is a slightly dodgy hack in that it pre-supposes the appearance of the ComboBox in this mode, but the functionality is only applied when the OS is identified as Vista or 7.
  • The control is inconsistent with other ComboBox controls because it is not animated. With the BufferedPainter<T> class I developed, implementing buffered animation was simple.

ComboTreeBox

The ComboTreeBox is a control developed entirely from scratch (i.e. its base class is Control) that uses a hierarchical/tree structure as its data representation (instead of a flat list). As such, it has behaviours in common with both ComboBox and TreeView. The drop-down/pop-up portion of the control is implemented using ToolStripDropDown, bitmap caching and custom rendering.

What’s new:

  • As with GroupedComboBox, the control did not appear in the Windows Vista/7 style. As the control has no editable portion and is entirely owner-drawn, it was easy to simulate the appearance under the appropriate OS. Under XP, it falls back to the default visual style. When themes are disabled, it draws in the classic style.
  • The control was not animated. Once again, BufferedPainter<T> was used to implement animation.
  • Due to a strongly-typed reference to its designer class, the control previously did not work with the “Client Profile” version of the .NET Framework. Rather cheekily, I have substituted my custom designer for the built-in designer that the DomainUpDown control uses – this works well for constraining the height of the control and avoids the need to reference the System.Design assembly (included only with the full version of the framework).
  • Minor tweaks were made to the way focused items are drawn; this is only apparent if focus cues are enabled in Windows.

Download

DropDownControlsUpdated.zip (Visual Studio 2010 Solution, .NET Framework 4 Client Profile)

Everything you need to know about the ABA file format

The ABA file format, sometimes called Direct Entry or Cemtext, is an unpublished de facto standard for bulk electronic payments. It is used by all major Australian financial institutions to interface with business accounting systems, and is supported by many popular accounting packages such as MYOB. For small-to-medium businesses, the most common usage for an ABA file is to upload it via their Internet banking portal – to avoid manually entering transaction details into the web application. As the name suggests, the format is dictated by the Australian Banking Association, and also has ties with the Australian Payments Clearing Association (APCA).

I was recently tasked with writing an exporter from a proprietary, relational database system to the ABA format. Since the specifications for the file format are not in the public domain (at least, not from an official source), I had to rely on some third-party sources to arrive at a solution. In this article, i’ll share those resources with you, as well as providing my own explanation of some of the finer points of the standard – to help you avoid common pitfalls when working with the format.

Overview of the ABA format

The ABA format is somewhat archaic; certainly based on outdated technology. It’s a plain-text format that uses fixed-width fields (most of which are severely constrained, to the point that most data going into them must be truncated or abbreviated in order to fit). It is not supposed to be human-readable, although a trained eye can interpret it. Its values are untyped and there is nothing to validate the correctness of an ABA file if you are not privy to the rules.

An ABA file consists of:

  • One ‘type 0′ record (i.e. line) which describes and provides instructions processing instructions for the batch
  • One or more ‘type 1′ records which provide the detail for each payment in the batch
  • One ‘type 7′ record which confirms the size and totals for the batch

(i.e. an ABA file is at least 3 lines long.)

Within each record/line in the file, and depending on the record type, there are a number of fixed-width fields which must be populated. Some are padded with zeroes, others with spaces. Some occupy the left portion of the field, others (like numeric fields) are right-justified. A complete line must consist of exactly 120 characters (excluding the CR/LF terminator). It’s helpful to write a function to perform the necessary padding/truncation and justification:

// requires a reference to System.Linq
string ToFixedWidth(string input, int length, char padding = ' ', bool rightJustify = false) {
	char[] output = new char[length];
	if (rightJustify) input = new string(input.Reverse().ToArray());

	for (int i = 0; i < length; i++) {
		if (i < input.Length)
			output[i] = input[i];
		else
			output[i] = padding;
	}

	if (rightJustify) output = output.Reverse().ToArray();
	return new string(output);
}

// to pad a string out to 18 characters, left-justified and padded with spaces:
ToFixedWidth(str, 18);

// to pad a decimal number out to 10 characters, right-justified and padded with zeroes:
ToFixedWidth((num * 100).ToString("0000000000"), 10, '0', true);

Some additional notes:

  • Most examples i’ve seen capitalise all text fields, however this is not necessary. Some financial institutions will retain the casing of your narrations/annotations, if only on the sender’s bank statement.
  • All dollar amounts are expressed in whole cents, with no digit grouping. Multiply your decimal figures by 100 and use an appropriate number format string (e.g. “0000000000″).

Resources for the file format specification

The following are two excellent resources for the specification of the ABA file format itself:

Between these two documents, you should have all the information you need to construct the ABA records themselves. There is some inherent ambiguity in these, however, which is why i’d like to add the following notes:

Descriptive record

Reel sequence number

There is a maximum number of payments you can include per ABA file, if only because the dollar amount and number of records fields are of a fixed length. If you need to split your batch into multiple files, the reel sequence number identifies each one. However, in the vast majority of cases, you will only have one file, numbered 01. You do not have to keep track of which numbers you have used previously.

User Preferred Specification

This is one of two pieces of information that identify the user and their financial institution. Some banks will dictate the value for this field, others are less restrictive and will permit any form of the name on the user’s bank account. It’s best to make the value for this field user-maintainable.

User Identification Number

Contrary to its description, this number identifies the financial institution, not the user. Each FI has its own number (or possibly several, depending on the size of the bank) which is issued by APCA. This number does not change between batches; it’s tied to the bank and, potentially, the account. Most banks document this number somewhere in their internet banking portal instructions.

Detail records

Indicator

As far as I can tell, this field can be used to indicate that a particular record represents a change to a prior record in the batch, or to existing details held on file for the payee. It’s also clear that not every financial institution pays attention to this field. Unless you are dealing with thousands of payments at a time, you should leave this field blank to make it clear that each record represents a separate payment.

Transaction code

In most cases, you should use the code 50, which represents a non-specific credit to the bank account. For payroll transactions, use the code 53. The other transaction codes appear to be of relevance to the ATO and superannuation funds only.

Lodgement reference

This is the text that appears on the payee’s bank statement.

Trace record (BSB and Account No)

This is the BSB and Account Number of your bank account.

Name of remitter

If your bank supports it, this lets you track the name of the person in your organisation who authorised the payment.

Final words

Hopefully, this points you in the direction of the right resources and helps to dispel some of the confusion surrounding the ABA file format. By following the specification exactly, you will produce a file that can be read by all major Australian banks and has the potential to save time and reduce errors when processing large numbers of payments.

Painting Controls With Fade Animations Using the Buffered Paint API

Windows Forms provides many mechanisms for building professional custom UI controls that match the operating system style; by combining visual style renderers, system colours/brushes, the ControlPaint class and more, it’s possible to reproduce most of the standard Windows controls in user code.

There is, however, one aspect of the built-in controls that can be difficult to recreate in managed code: Starting with Windows Vista, fade animations are used for many controls (e.g. Button, ComboBox, TextBox, etc) when transitioning between states such as focus, mouse-over and button pressing. Internally, these animations are handled by the buffered paint API (part of uxtheme.dll, the library responsible for visual styles).

Most developers would be content with instantaneous visual state changes, but to the trained eye, the lack of smooth transitions can really make a custom control stand out from a built-in one. The good news is that, although there is no managed API for buffered painting, it’s relative easy to harness using PInvoke.

Buffered Paint API – The Basics

Imports

[DllImport("uxtheme")]
static extern IntPtr BufferedPaintInit();

[DllImport("uxtheme")]
static extern IntPtr BufferedPaintUnInit();

[DllImport("uxtheme")]
static extern IntPtr BeginBufferedAnimation(
    IntPtr hwnd,
    IntPtr hdcTarget,
    ref Rectangle rcTarget,
    BP_BUFFERFORMAT dwFormat,
    IntPtr pPaintParams,
    ref BP_ANIMATIONPARAMS pAnimationParams,
    out IntPtr phdcFrom,
    out IntPtr phdcTo
);

[DllImport("uxtheme")]
static extern IntPtr EndBufferedAnimation(IntPtr hbpAnimation, bool fUpdateTarget);

[DllImport("uxtheme")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool BufferedPaintRenderAnimation(IntPtr hwnd, IntPtr hdcTarget);

[DllImport("uxtheme")]
static extern IntPtr BufferedPaintStopAllAnimations(IntPtr hwnd);

Usage

  • You initialise/end a session (typically lasting for the life of the control) using BufferedPaintInit/BufferedPaintUnInit.
  • You begin a fade animation with BeginBufferedAnimation, passing in a BP_ANIMATIONPARAMS structure to describe the transition. A handle to the animation and two empty bitmaps are returned.
  • You paint the start and end frames onto the respective bitmaps (using GDI+, as if you were painting the control normally) and call EndBufferedAnimation to start playing it.
  • While the animation is playing, the control’s Paint event will be fired multiple times. Check to see whether it was triggered by the buffered paint animation by checking the value returned by BufferedPaintRenderAnimation; if so, don’t paint the control yourself.
void Control_Paint(object sender, PaintEventArgs e) {
    IntPtr hdc = e.Graphics.GetHdc();
    if (hdc != IntPtr.Zero) {
        // see if this paint was generated by a soft-fade animation
        if (!Interop.BufferedPaintRenderAnimation(Control.Handle, hdc)) {
            BP_ANIMATIONPARAMS animParams = new BP_ANIMATIONPARAMS();
            animParams.cbSize = Marshal.SizeOf(animParams);
            animParams.style = BP_ANIMATIONSTYLE.BPAS_LINEAR;

            // set duration according to state transition
            animParams.dwDuration = 125;

            // begin the animation
            Rectangle rc = Control.ClientRectangle;
            IntPtr hdcFrom, hdcTo;
            IntPtr hbpAnimation = Interop.BeginBufferedAnimation(
                Control.Handle,
                hdc,
                ref rc,
                BP_BUFFERFORMAT.BPBF_COMPATIBLEBITMAP,
                IntPtr.Zero,
                ref animParams,
                out hdcFrom,
                out hdcTo
            );

            if (hbpAnimation != IntPtr.Zero) {
                if (hdcFrom != IntPtr.Zero) /* paint start frame to hdcFrom */;
                if (hdcTo != IntPtr.Zero) /* paint end frame to hdcTo */;
                Interop.EndBufferedAnimation(hbpAnimation, true);
            }
            else {
                /* paint control normally */
            }
        }

        e.Graphics.ReleaseHdc(hdc);
    }
}

Some further notes about using the buffered paint API on Windows Forms controls:

  • Animations are not supported if the control is double-buffered (DoubleBuffered property set to true or OptimizedDoubleBuffer style flag set).
  • To reduce flickering, override the control’s OnPaintBackground method and don’t call the base class method. You can paint the control’s background manually when you paint the rest of it.
  • Whenever the control is resized, all running animations should be stopped using BufferedPaintStopAllAnimations.

BufferedPainter – A Managed Class to Simplify Buffered Painting

Buffered painting involves a certain amount of boilerplate code. You need to add code to the control’s creation/disposal events, override the Paint event using a particular pattern and then provide an alternative method for painting the control (either to the screen or to a bitmap).

One way to eliminate this boilerplate code would be to write a base class, derived from Control, which provided this functionality. This is somewhat limiting, however, as all custom controls using buffered painting would have to inherit from this class. In reality, you are likely to want to use buffered painting both in completely new controls and when subclassing existing controls (e.g. ComboBox). For this reason, i’ve written a class which sits in isolation and attaches to any type of control.

BufferedPainter is a generic class which allows any type to be used to represent a control’s visual state; this may be an enumeration, an integer or even a more complex type. As long as the type provides an Equals method (or has a suitable default implementation), it can be used to track state transitions. A simple button control might have three states; Normal, Hot and Pushed. BufferedPainter holds information about state changes and the duration of animations between states (where desired). It stores the current visual state of the control, overrides the control’s Paint event and provides a PaintVisualState event to be handled by user code.

It also provides a mechanism to simplify the process of triggering changes in the control’s visual state; in addition to manually setting the state of the control (using the State property), you can add a trigger which changes to a particular state in response to a condition (such as the mouse being over the control). This further reduces the amount of code necessary in the control. Conditions can be specific to a region within the control’s bounds, and anchoring can be used to automatically update the region when the control is resized.

Adding buffered paint support to a control is as simple as:

// using an enum type 'MyVisualStates' to describe the control's visual state
BufferedPainter<MyVisualStates> painter = new BufferedPainter<MyVisualStates>(/* control instance */);
painter.PaintVisualState += /* event handler which paints the control in a particular state */;

// describe the state transitions we want to animate
painter.AddTransition(MyVisualStates.Normal, MyVisualStates.Hot, 125); // fade in
painter.AddTransition(MyVisualStates.Hot, MyVisualStates.Pushed, 75);
painter.AddTransition(MyVisualStates.Hot, MyVisualStates.Normal, 250); // fade out

// describe what causes the control to change its visual state
painter.AddTrigger(VisualStateTriggerTypes.Hot, MyVisualStates.Hot); // mouse over
painter.AddTrigger(VisualStateTriggerTypes.Pushed, MyVisualStates.Pushed); // mouse down

Download

BufferedPainting.zip (includes example control)

Final Words

The buffered paint API closes one of the final gaps in writing custom controls in managed code which match the OS style, both in terms of static appearance and animation. I hope you find my code useful in implementing smooth transitions in your own custom controls.