Pocket PC – Actually closing a form

You would be forgiven for thinking that clicking on the ‘X’ in the top right of your form would close it, as per all standard Windows applications…but be warned this is NOT the case with Pocket PC applications! I’m not sure what the wisdom is behind this decision, I guess it doesn’t really matter, I just wish it were more obvious!

Anyway, clicking the cross does nothing more than minimise your form, in order to fully close it, you must set it’s ‘MinimizeBox’ property to false. This will in turn display an ‘ok’ button instead of a ‘X’ at the top of your form, and it is clicking this ‘ok’ button that fires the form closing events!…obvious when you think about it!…hmmmmm.

So there’s an hour of my life I’ll never get back! Thanks Microsoft.

Advertisements

Sending raw data to a printer

An awesome printer helper class for sending raw data to a printer. I have found this very useful for sending control codes to our Datamax label printers at work for barcode printing etc.

I added an additional method to the helper class (bodged together from the existing ones!) that accepts a memory stream instead of a file or string.

public static bool SendStreamToPrinter(string szPrinterName, MemoryStream ms, string DocName)
{
    // Open the file.
    //FileStream fs = new FileStream(szFileName, FileMode.Open);
    // Create a BinaryReader on the file.
    BinaryReader br = new BinaryReader(ms);
    // Dim an array of bytes big enough to hold the file's contents.
    Byte[] bytes = new Byte[ms.Length];
    bool bSuccess = false;
    // Your unmanaged pointer.
    IntPtr pUnmanagedBytes = new IntPtr(0);
    int nLength;

    nLength = Convert.ToInt32(ms.Length);
    // Read the contents of the file into the array.
    bytes = br.ReadBytes(nLength);
    // Allocate some unmanaged memory for those bytes.
    pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
    // Copy the managed byte array into the unmanaged array.
    Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
    // Send the unmanaged bytes to the printer.
    bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength, DocName);
    // Free the unmanaged memory that you allocated earlier.
    Marshal.FreeCoTaskMem(pUnmanagedBytes);
    return bSuccess;
}

Barcode Scanning

This week marked my first foray into the world of the .NET Compact Framework. We’re using Motorola MC9090 scanners running Windows Mobile 5.0 and our application needs to read scanned barcodes directly into an existing SQL Server database.

First job was to download the Motorola EMDK kit containing the relevant .dll’s for the scanners, it even comes with a sample project demo’ing how to use them. The two main classes of note are symbol.barcode.reader and symbol.barcode.readerdata, which are pretty self explanatory and deal with the scanned data from the scanner. You need to setup a Reader object to read from the scanner and a ReaderData object to handle the read data (see told you they were self explanatory) and probably an event handler to do something with it once you have scanned.

The code snippet below demonstrates how to capture scanned data and display in a Windows MessageBox. (I’m using a Windows Smart Device Application for Windows Mobile 5.0 and .NET compact Framework 3.5)..

public partial class Form1 : Form
{
    //setup Reader & ReaderData objects
    Symbol.Barcode.Reader barcodeReader = null;
    Symbol.Barcode.ReaderData barcodeReaderData = null;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        barcodeReader = new Symbol.Barcode.Reader();
        //sets up ReaderData to receive text and allocates max buffer size for barcode (7905 bytes).
        barcodeReaderData = new Symbol.Barcode.ReaderData(Symbol.Barcode.ReaderDataTypes.Text, Symbol.Barcode.ReaderDataLengths.MaximumLabel);

        barcodeReader.Actions.Enable();  //enable scanner hardware.
        barcodeReader.ReadNotify += new EventHandler(barcodeReader_Read);  //eventHandler for when read is complete.
        barcodeReader.Actions.Read(barcodeReaderData);  //read scan.          
    }

    private void barcodeReader_Read(object sender, EventArgs e)
    {
        Symbol.Barcode.ReaderData nextReaderData = barcodeReader.GetNextReaderData();  //Get(s)NextReaderData
        MessageBox.Show(nextReaderData.Text);  //Display output in messagebox.
        barcodeReader.Actions.Read(barcodeReaderData);  //await next scan.
    }

    private void Form1_Closing(object sender, CancelEventArgs e)
    {
        //Dispose of everything
        barcodeReader.Actions.Flush();
        barcodeReader.Actions.Disable();
        barcodeReader.Dispose();
        barcodeReaderData.Dispose();
    }
}

Regular Expressions

Have been reading a little bit about string manipulation and in particular regular expressions. Having never used them before, I was a little unsure as to their uses and applications however they appear to be very useful indeed.

Regular Expressions allow you real control when processing text, meaning you can match/validate/replace/search even large amounts of text with relative ease. I have only scratched the surface so far, but can already imagine a number of applications for such text manipulation – not least the ‘Cipher Breaker’ program I am writing at the moment where it is necessary to perform frequency analysis and string replacement over large blocks of coded text.

The following code snippet shows how you can use a regular expression to mask a textbox, in this instance the textbox is masked xxx-xxx-xxx-xxx.

private void textBox1_Validating(object sender, CancelEventArgs e)
{
    string strMask = "^\\d{3}-\\d{3}-\\d{3}-\\d{3}$";

    if (Regex.IsMatch(textBox1.Text, strMask))
    {
         MessageBox.Show("Format Correct");
    }
    else
    {
        MessageBox.Show("Format Incorrect, re-enter using: xxx-xxx-xxx-xxx");
    }
}

For more information about regular expressions and their uses (including language elements), see the two links below:

http://msdn.microsoft.com/en-us/library/hs600312.aspx
http://msdn.microsoft.com/en-us/library/az24scfc(v=vs.80).aspx
http://www.regxlib.com/DisplayPatterns.aspx?cattabindex=4&categoryId=5