RSS

Category Archives: Window Application

Image Resizing and Cropping in C#

By: JasonJano’s Blog

So the other day I put up a c# wrapper for ffmpeg. The wrapper I built is a part of my own asset storage system which I guess I will probably be putting up in chunks over the next few weeks. Today I have decided to put up my image resizing tools for your use.

Resize Now or Resize Later?

There are a couple theories to image resizing, should the image be resized at the point it gets uploaded, or at the point it gets sent out to the client?

Each method has advantages and disadvantages. Resizing at upload is good because it speeds up time to delivery as the processor has already done the resizing, additionally, the image is only resized once, vs. if the image is resized every time it is downloaded, it could be resized countless times. The problem with resizing at upload, however, is that it is now resized — you can’t un-resize it. Resizing at download then, is more processor intensive as it is resized every time someone requests a different size (one could probably get around some of this with caching, but the no matter how you slice it, it is still more processor intensive). The nice thing is that based on querystring or, however you pass the resizer data, you get a customized image size.

I have my own theory on this. If one has a ton of storage space (which most of us do have available to us now adays) it makes sense to resize in some basic sizes at upload while keeping the original as well for future resizing, if needed. Most good graphic designers break all their pages up into grids of magic 3rds anyways and would, generally, have ideas about their perfect image sizes for thumbnails, swatches, large previews, etc..

In another post I will detail how I get all of these different sizes and what not stored for use, but — for now — I will just give you the tools with which to do resizing and cropping in one spot.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
//Overload for crop that default starts top left of the image.
public static System.Drawing.Image CropImage(System.Drawing.Image Image, int Height, int Width)
{
    return CropImage(Image, Height, Width, 0,0);
}
//The crop image sub
public static System.Drawing.Image CropImage(System.Drawing.Image Image, int Height, int Width, int StartAtX, int StartAtY)
{
    Image outimage;
    MemoryStream mm = null;
    try
    {
        //check the image height against our desired image height
        if (Image.Height < Height) {
            Height = Image.Height;
        }
        
        if (Image.Width < Width) {
            Width = Image.Width;
        }
        
        //create a bitmap window for cropping
        Bitmap bmPhoto = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
        bmPhoto.SetResolution(72, 72);
        
        //create a new graphics object from our image and set properties
        Graphics grPhoto = Graphics.FromImage(bmPhoto);
        grPhoto.SmoothingMode = SmoothingMode.AntiAlias;
        grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
        grPhoto.PixelOffsetMode = PixelOffsetMode.HighQuality;
        
        //now do the crop
        grPhoto.DrawImage(Image, new Rectangle(0, 0, Width, Height), StartAtX, StartAtY, Width, Height, GraphicsUnit.Pixel);
        
        // Save out to memory and get an image from it to send back out the method.
        mm = new MemoryStream();
        bmPhoto.Save(mm, System.Drawing.Imaging.ImageFormat.Jpeg);
        Image.Dispose();
        bmPhoto.Dispose();
        grPhoto.Dispose();
        outimage = Image.FromStream(mm);
        return outimage;
    }
    catch (Exception ex)
    {
        throw new Exception("Error cropping image, the error was: " + ex.Message);
    }
}
//Hard resize attempts to resize as close as it can to the desired size and then crops the excess
public static System.Drawing.Image HardResizeImage(int Width, int Height, System.Drawing.Image Image)
{
    int width = Image.Width;
    int height = Image.Height;
    Image resized = null;
    if (Width > Height)
    {
        resized = ResizeImage(Width, Width, Image);
    }
    else
    {
        resized = ResizeImage(Height, Height, Image);
    }
    Image output = CropImage(resized, Height, Width);
    //return the original resized image
    return output;
}
//Image resizing
public static System.Drawing.Image ResizeImage(int maxWidth, int maxHeight, System.Drawing.Image Image)
{
    int width = Image.Width;
    int height = Image.Height;
    if (width > maxWidth || height > maxHeight)
    {
        //The flips are in here to prevent any embedded image thumbnails -- usually from cameras
        //from displaying as the thumbnail image later, in other words, we want a clean
        //resize, not a grainy one.
        Image.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipX);
        Image.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipX);
        float ratio = 0;
        if (width > height)
        {
            ratio = (float)width / (float)height;
            width = maxWidth;
            height = Convert.ToInt32(Math.Round((float)width / ratio));
        }
        else
        {
            ratio = (float)height / (float)width;
            height = maxHeight;
            width = Convert.ToInt32(Math.Round((float)height / ratio));
        }
        //return the resized image
        return Image.GetThumbnailImage(width, height, null, IntPtr.Zero);
    }
    //return the original resized image
    return Image;
}

Copy from: https://jasonjano.wordpress.com/2010/02/13/image-resizing-and-cropping-in-c/

 
Leave a comment

Posted by on January 26, 2015 in C#, Window Application

 

How to: Create Item Templates

The steps in the first procedure of this topic show you how to create an item template by using the Export Template wizard.

If you plan to use the item in a Windows Store app project, you’ll have to perform a few extra steps. The second procedure in this topic helps you accomplish that task.

Note Note
You cannot export templates for C++ projects.

To add a custom project item template to the Add New Item dialog box

  1. Create or open a project in Visual Studio.
  2. Add an item to the project and modify it if you want to.
  3. Modify the code file to indicate where parameter replacement should take place. For more information, see How to: Substitute Parameters in a Template.
  4. On the File menu, click Export Template.
  5. Click Item Template, select the project that contains the item, and click Next.
  6. Select the item for which you want to create a template, and click Next.
  7. Select the assembly references to include in the template, and click Next.
  8. Type the icon file name, preview image, template name, and template description, and click Finish.

    The files for the template are added to a .zip file and copied to the ..\Users\username\Documents\Visual Studio Version\Templates\ItemTemplates\ folder.

To enable the item template to be used in a Windows Store project

  1. Follow the steps in the procedure above to export an item template.
  2. Extract the .vstemplate file from the .zip file that was copied to the ..\Users\username\Documents\Visual Studio Version\Templates\ItemTemplates\ folder.
  3. Open the .vstemplate file in Notepad.
  4. In the .vstemplate file, add the following XML within the opening and closing <TemplateData> tag: <TemplateGroupID>WinRT-Managed</TemplateGroupID>.

    The following example shows the entire contents of a .vstemplate file after the line of XML <TemplateGroupID>WinRT-Managed</TemplateGroupID> has been added to it.

    <VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Item">
      <TemplateData>
        <DefaultName>MyItemStoreTemplate.xaml</DefaultName>
        <Name>MyItemStoreTemplate</Name>
        <Description>This is an example itemtemplate</Description>
        <ProjectType>CSharp</ProjectType>
        <SortOrder>10</SortOrder>
        <Icon>__TemplateIcon.ico</Icon>
        <TemplateGroupID>WinRT-Managed</TemplateGroupID>
      </TemplateData>
      <TemplateContent>
        <References />
        <ProjectItem SubType="Designer" TargetFileName="$fileinputname$.xaml" ReplaceParameters="true">MyItemTemplate.xaml</ProjectItem>
        <ProjectItem SubType="Code" TargetFileName="$fileinputname$.xaml.cs" ReplaceParameters="true">MyItemTemplate.xaml.cs</ProjectItem>
      </TemplateContent>
    </VSTemplate>
    
  5. In Notepad, save the .vstemplate file and close it.
  6. Copy and paste the .vstemplate file back to the .zip file located in the ..\Users\username\Documents\Visual Studio Version\Templates\ItemTemplates\ folder.

    If the Copy File dialog box appears, choose the Copy and Replace option.

You can now add an item based on this template to a Windows Store project by using the Add New Item dialog box.

Copy from: http://msdn.microsoft.com/en-us/library/tsyyf0yh.aspx

 
Leave a comment

Posted by on April 5, 2014 in C#, Window Application

 

IDM (Internet download manager) API using C#?

By: Simon Mourier

You should

1) download IDMCOMAPI.zip to your disk

2) extract the IDManTypeInfo.tlb type library from this zip file, somewhere on your disk

3) run The Type Library Importer tool like this:

[C:\Temp]"c:\Program Files\Microsoft SDKs\Windows\\v7.1\Bin\TlbImp.exe" IDManTypeInfo.tlb
Microsoft (R) .NET Framework Type Library to Assembly Converter 3.5.30729.1
Copyright (C) Microsoft Corporation.  All rights reserved.

Type library imported to IDManLib.dll

This will create an IDManLib.dll

4) Now you can reference IDManLib.dll in your project. I have not tested it, but I also suppose you want to ensure your program is compiled with the proper bitness (it depends how the IDM COM Server works). So, I suggest you compile as X86 (not anyCpu, not X64).

Copy from : http://stackoverflow.com/questions/9150466/idm-internet-download-manager-api-using-c

 
Leave a comment

Posted by on July 18, 2013 in C#, Window Application

 

Catch scroll to end of DataGridView in C#

How to catch when the user scrolls to the bottom of the dataGridView, so I can load more results:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication30
{

    public partial class Form1 : Form
    {

        private DateTime lastLoading;
        private int firstVisibleRow;
        private ScrollBars gridScrollBars;

        public Form1()
        {
            InitializeComponent();

            //attach scroll event.
            dataGridView1.Scroll += new ScrollEventHandler(dataGridView1_Scroll);

            //load firs 100 rows.
            LoadRows();
        }

        private void HideScrollBars()
        {
            gridScrollBars = dataGridView1.ScrollBars;
            dataGridView1.ScrollBars = ScrollBars.None;
        }

        private void ShowScrollBars()
        {
            dataGridView1.ScrollBars = gridScrollBars;
        }

        private int GetDisplayedRowsCount()
        {
            int count = dataGridView1.Rows[dataGridView1.FirstDisplayedScrollingRowIndex].Height;
            count = dataGridView1.Height / count;
            return count;
        }

        private void LoadRows()
        {
            HideScrollBars();

            System.Diagnostics.Debug.WriteLine("Load data");
            lastLoading = DateTime.Now;

            //create rows
            for (int i = 0; i < 100; i++)
            {
                int n =dataGridView1.Rows.Add();
                dataGridView1.Rows[n].Cells[0].Value = "Row - " + n.ToString();
            }

            //reset displayed row
            if (firstVisibleRow > -1)
            {
                ShowScrollBars();
                dataGridView1.FirstDisplayedScrollingRowIndex = firstVisibleRow;
            }
        }

        void dataGridView1_Scroll(object sender, ScrollEventArgs e)
        {
            if (e.Type == ScrollEventType.SmallIncrement || e.Type == ScrollEventType.LargeIncrement)
            {
                if (e.NewValue >= dataGridView1.Rows.Count - GetDisplayedRowsCount())
                {
                    //prevent loading from autoscroll.
                    TimeSpan ts = DateTime.Now - lastLoading;
                    if (ts.TotalMilliseconds > 100)
                    {
                        firstVisibleRow = e.NewValue;
                        LoadRows();
                    }
                    else
                    {
                        dataGridView1.FirstDisplayedScrollingRowIndex = e.OldValue;
                    }
                }
            }
        }
    }
}

private DateTime lastLoading;
In this variable I save last loading time and it is used to prevent “loading while loading” (scroll event is fired while loading because of the automatic scrolling) . Interval between loading in this example is 100 ms.

  private int firstVisibleRow;

In this variable I save first visible row index before loading and set datagridview first visible row after loading. This is also used because of the automatic scrolling.

        private ScrollBars gridScrollBars;

In this variable I save datagridview scrollbars property and it is used to force scrollbar update because scrollbar is not updated after loading.

   //attach scroll event.
            dataGridView1.Scroll += new ScrollEventHandler(dataGridView1_Scroll);

In this line I just atach datagridview scroll event.

            //load firs 100 rows.
            LoadRows();

In this line I load first 100 rows on startup. I use this method because in my test application I don’t have any data and this simulate real loading.

        private void HideScrollBars()
        {
            gridScrollBars = dataGridView1.ScrollBars;
            dataGridView1.ScrollBars = ScrollBars.None;
        }

In this method I save datagridview scrollbars in variable and hide scrollbars. (update scrollbars after loading).

    private void ShowScrollBars()
        {
            dataGridView1.ScrollBars = gridScrollBars;
        }

In this method I show datagridview scrollbars. (update scrollbars after loading).

        private int GetDisplayedRowsCount()
        {
            int count = dataGridView1.Rows[dataGridView1.FirstDisplayedScrollingRowIndex].Height;
            count = dataGridView1.Height / count;
            return count;
        }

In this method I calculate number of visible rows. This is needed because value in datagridview scroll event (e.NewValue) is index of first visible row in datagridview.

        private void LoadRows()
        {
            HideScrollBars();

            System.Diagnostics.Debug.WriteLine("Load data");
            lastLoading = DateTime.Now;

            //create rows
            for (int i = 0; i < 100; i++)
            {
                int n =dataGridView1.Rows.Add();
                dataGridView1.Rows[n].Cells[0].Value = "Row - " + n.ToString();
            }

            //reset displayed row
            if (firstVisibleRow > -1)
            {
                ShowScrollBars();
                dataGridView1.FirstDisplayedScrollingRowIndex = firstVisibleRow;
            }
        }

In this method I create rows in grid and you should replace for loop with your load data. You need code which is before and after loop.

    void dataGridView1_Scroll(object sender, ScrollEventArgs e)
        {
            if (e.Type == ScrollEventType.SmallIncrement || e.Type == ScrollEventType.LargeIncrement)
            {
                if (e.NewValue >= dataGridView1.Rows.Count - GetDisplayedRowsCount())
                {
                    //prevent loading from autoscroll.
                    TimeSpan ts = DateTime.Now - lastLoading;
                    if (ts.TotalMilliseconds > 100)
                    {
                        firstVisibleRow = e.NewValue;
                        LoadRows();
                    }
                    else
                    {
                        dataGridView1.FirstDisplayedScrollingRowIndex = e.OldValue;
                    }
                }
            }

In this event handler I do few thing:

– Check scroll event type – because we need to load data only in scroll down

– Get new value from event args (e.NewValue) – this is index of first displayed row in grid

– Get displayed rows count – rows in view

– Check if new value is bigger or equal to last row in grid – if yes.. then load more data

– Check last loading time – prevent “loading from loading” (workaround for grid autoscroll)

Referenced by: http://social.msdn.microsoft.com/Forums/en-SG/Vsexpressvcs/thread/4a882eff-f6dd-4d8f-86d9-e3d85947522e

 
2 Comments

Posted by on January 3, 2012 in C#, Window Application

 

How to create a setup project for a Windows Service application in Visual C#

This article describes how to create a setup project for a Windows Service application (formerly named an “NT service”). To do this, you must first create a solution that contains a simple Windows Service project that writes an entry to its application log. You then add a setup project to the solution to install the Window Service. Finally, you start the service. You can start the service by using the Services item in the Administrative Tools folder in the Start menu.

Requirements

The following list outlines the recommended hardware, software, network infrastructure, and service packs that you must have:

  • Microsoft Windows 2000, Windows XP, Windows Server 2003, or a later Microsoft operating system with the .NET Framework installed
  • Microsoft Visual Studio .NET Enterprise, Microsoft Visual Studio .NET Enterprise Architect, Microsoft Visual Studio 2005, or Microsoft Visual Studio 2008.

This article assumes that you are familiar with Windows Services. If you are not familiar with Windows Services, see the first reference in the REFERENCES section of this article.

This article also assumes that the user account that you use to install and to run this service has the permissions that you must have to install and to start services, and also has the permissions that you must have to access the event log.

Create a Setup Project for a Windows Service

This section describes how to create a Windows Service project, and how to use a compiled setup project to install the Windows Service.

Create a Windows Service Project

  1. Start Microsoft Visual Studio.
  2. On the File menu, point to New, and then click Project.
  3. Click Visual C# Projects under Project Types, and then click Windows Service under Templates.Note In Visual Studio 2005 or Visual Studio 2008, expand Visual C# under Project Types, clickWindows, and then click Windows Service under Templates.
  4. Type LogWriterService in the Name text box, and then type C:\ in the Location text box. Click OK.
  5. In Solution Explorer, right-click Service1.cs, and then click View Code.
  6. In the OnStart event handler, replace the comments with the following code:
    EventLog.WriteEntry("My simple service started.");
  7. In Solution Explorer, double-click Service1.cs.
  8. In the Code Editor window, right-click Design View, and then click Properties
  9. In the Properties pane, click the Add Installer link.
  10. In the Properties pane for ServiceInstaller1, change the ServiceName property to Service1.
  11. In the Code Editor window in Design view, click ServiceProcessInstaller1.
  12. In the Properties pane, change the Account property to LocalSystem (The LocalService andNetworkService values are available only in Microsoft Windows XP).

Use a Compiled Setup Project to Install the Windows Service

After you complete the steps in the previous section to configure the Windows Service project, follow these steps to add a deployment project that packages the service application so that the service application can be installed:

  1. Add a new project to your LogWriterService project. To do this, follow these steps:
    1. In Solution Explorer, right-click Solution ‘LogWriterService’ (1 project), point to Add, and then click New Project.
    2. Click Setup and Deployment Projects under Project Types, and then click Setup Projectunder Templates.
    3. In the Name text box, type ServiceSetup.
    4. Type C:\ in the Location text box, and then click OK.
  2. Tell the deployment project what to package. To do this, follow these steps:
    1. In Solution Explorer, right-click ServiceSetup, point to Add, and then click Project Output
    2. In the Add Project Output Group dialog box, in the Project box, click LogWriterService
    3. Click Primary Output, and then click OK.
  3. For correct installation, add only primary output. To add the custom actions, follow these steps:
    1. In Solution Explorer, right-click ServiceSetup, point to View, and then click Custom Actions
    2. Right-click Custom Actions, and then click Add Custom Action.
    3. Click Application Folder, and then click OK.
    4. Click Primary output from LogWriterService (Active), and then click OK.Notice that Primary output appears under InstallCommitRollback and Uninstall.
  4. By default, setup projects are not included in the build configuration. To build the solution, use one of the following methods:
    • Method 1
      1. Right-click LogWriterService, and then click Build.
      2. Right-click ServiceSetup, and then click Build.
    • Method 2
      1. On the Build menu, click Configuration Manager to build the whole solution.
      2. Click to select the Build check box for ServiceSetup.
      3. Press F7 to build the whole solution. When the solution is built, you have a complete installation package that is available for the service.
  5. To install the newly built service, right-click ServiceSetup, and then click Install.
  6. In the ServiceSetup dialog box, click Next three times. Notice that a progress bar appears while the service installs.
  7. When the service is installed, click Close.

Complete Code Listing

Service1.cs

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;

namespace LogWriterService
{
	public class Service1 : System.ServiceProcess.ServiceBase
	{
		/// <summary> 
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public Service1()
		{
			// The Windows.Forms Component Designer must have this call.
			InitializeComponent();

			// TODO: Add any initialization after the InitComponent call
		}

		// The main entry point for the process
		static void Main()
		{
			System.ServiceProcess.ServiceBase[] ServicesToRun;

			// More than one user service may run in the same process. To add
			// another service to this process, change the following line to
			// create a second service object. For example,
			//
			//   ServicesToRun = New System.ServiceProcess.ServiceBase[] {new Service1(), new MySecondUserService()};
			//
			ServicesToRun = new System.ServiceProcess.ServiceBase[] { new Service1() };

			System.ServiceProcess.ServiceBase.Run(ServicesToRun);
		}

		/// <summary> 
		/// Required method for Designer support - do not modify 
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			components = new System.ComponentModel.Container();
			this.ServiceName = "Service1";
		}

		/// <summary>
		/// Clean up any resources that are being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		/// <summary>
		/// Set things in motion so your service can do its work.
		/// </summary>
		protected override void OnStart(string[] args)
		{
			EventLog.WriteEntry("My simple service started.");
		}

		/// <summary>
		/// Stop this service.
		/// </summary>
		protected override void OnStop()
		{
			// TODO: Add code here to perform any tear-down necessary to stop your service.
		}
	}
}

Verify That It Works

  1. In Control Panel, double-click Administrative Tools, and then double-click Services
  2. Right-click Service1, and then click Start
  3. Use one of the following methods to verify that an event is logged in the event log:
    • Method 1
      1. In Control Panel, double-click Administrative Tools, and then double-click Event Viewer.
      2. Click Application Log in the left pane, and then locate the event log for your service from the right pane.
    • Method 2
      1. In Server Explorer, expand Servers, expand ComputerName, expand Event Logs, expand Application, and then expand Service1. Recall that Service1 is the name of the class, not the service itself. Therefore, Service1 is used as the application name. (It is beyond the scope of this article to explain how to customize the names.)
      2. Move the cursor over the log entries. The second entry from the top should read “My simple service started”.

Referenced by: http://support.microsoft.com/kb/816169

 
Leave a comment

Posted by on December 9, 2011 in C#, Window Application

 

GenCode128 – A Code128 Barcode Generator

Sample Image - GenCode128.png

Introduction

This is a simple library that lets you do one thing very easily: generate an Image for a Code128 barcode, with a single line of code. This image is suitable for print or display in a WinForms application, or even in ASP.NET.

Background

Support for other barcode symbologies can be easily found because they’re easy to create. Basic Code39 barcodes, for example, can be produced using nothing but a simple font, and it seems like you can’t hardly swing a cat without hitting a Code39 font or imageset for download.

However, Code39 has deficiencies. The naive font-derived output doesn’t afford any error checking. In their standard configuration, most scanners can only recognize 43 different symbols (configuration changes may fix this, but you may not have that luxury with your users’ choice of hardware configuration). And Code39 is fairly verbose, requiring a large amount of space for a given message.

Code128, on the other hand, has out-of-the-box support for all 128 low-order ASCII characters. It has built-in error detection at the character and message level, and is extremely terse. Unfortunately, producing a reasonable encoding in this symbology is an “active” process. You must analyze the message for the optimal encoding strategy, and you must calculate a checksum for the entire message.

In my case, it was an absolute necessity to encode control characters. My application’s design demanded that the user be able to trigger certain menu shortcut keys by scanning a barcode on a page. But since I’ve got no control over the scanners that my users are employing, the Code39EXT symbology wasn’t a good candidate.

A search yielded several Code128 controls, but these had two important deficiencies. First, they were controls. That would be fine if I just wanted to produce a barcode on the page, but I wanted to use them as images in a grid, so I needed a means of obtaining a raw GDI+ Image object. Second, they were fairly expensive — enough that a license covering all of our developers would cost more than my time to roll my own.

Using the code

Basic usage

As promised, producing the barcode Image is as simple as a single line of code. Of course, you’ll still need code lines necessary to put that Image where it needs to go.

Here’s a chunk from the sample application. In it, I respond to a button click by generating a barcode based on some input text, and putting the result into a PictureBox control:

 Collapse | Copy Code
private void cmdMakeBarcode_Click(object sender, System.EventArgs e)
{
   try
   {
      Image myimg = Code128Rendering.MakeBarcodeImage(txtInput.Text, 
                                         int.Parse(txtWeight.Text), true);
      pictBarcode.Image = myimg;
   }
   catch (Exception ex)
   {
      MessageBox.Show(this, ex.Message, this.Text);
   }
}

Obviously, the meat of this is the first line following the try. For the caller, there’s just one interesting method in the whole library:

 Collapse | Copy Code
GenCode128.Code128Rendering.MakeBarcodeImage( string InputData, 
                              int BarWeight, bool AddQuietZone )

(That’s the GenCode128 namespace, in a static class called Code128Rendering). Since this is a static class, you don’t even need to worry about instantiating an object.

There are three parameters:

  • string InputDataThe message to be encoded
  • int BarWeightThe baseline width of the bars in the output. Usually, 1 or 2 is good.
  • bool AddQuietZoneIf false, omits the required white space at the start and end of the barcode. If your layout doesn’t already provide good margins around the Image, you should use true.

You can get a feel for the effect of these values by playing with the sample application. While you’re at it, try printing out some samples to verify that your scanners can read the barcodes you’re planning to produce.

Printing

A barcode library is pretty much useless if you don’t use it to print. You can’t very well scan the screen. It’s been quite a long time since I had printed anything from a Windows application, and it took a little while to remember how. If you need a quick reminder like I did, take a look at the event that the demo app’s Print button calls.

What you should be aware of

First of all, I don’t have any exception handling built into the library itself. For your own safety, you should puttry/catch blocks around any calls to the library.

The solution comprises three projects. One is the library itself, one is the demo application, and then there is the unit test code. I used NUnit by way of TestDriven.net. If you don’t have that, then Visual Studio is going to complain. Since it’s just test code, you can safely drop it and still use the library successfully.

Another point is the required vertical height of the barcode. The spec requires that the image be either 1/4″ or 15% of the overall width, whichever is larger. Since I don’t have any control of the scaling you’re using when outputting the image, I didn’t bother implementing the 1/4″ minimum. This means that for very short barcode, the height might be illegally small.

Code128’s high information density derives partly from intelligently shifting between several alternate codesets. Obtaining the optimal encoding is, as far as I can tell, a “hard” problem (in the sense of discrete math’s non-polynomial problems like the Traveling Salesman). The difference between the best possible solution and my pretty good one should be small, and doesn’t seem worth the effort.

My algorithm for obtaining a “pretty good” encoding involves a single-character look-ahead.

  • If the current character can be encoded in the current codeset, then it just goes ahead and does so.
  • Otherwise, if the next character would be legal in this codeset, it temporarily shifts into the alternate codeset for just this character.
  • Else, both this character and the next would need a shift, so instead it changes codesets to avoid the shifts.

A similar decision has to be made about which codeset to start the encoding in. To solve this, I check the first two characters of the string, letting them “vote” to see which codeset they prefer. If there’s a preference for one codeset, I choose it; otherwise, I default to codeset B. This is because codeset A allows uppercase alpha-numerics plus control characters, while codeset B allows upper and lower alpha-numerics; I assume that you’re more likely to want lowercase than control characters.

Finally, there is an optimization in the Code128 spec for numeric-only output that I didn’t take advantage of. Long runs of digits can be encoded in a double density codeset. Accounting for this in my already-ugly look-ahead algorithm would have taken a lot more effort — for a feature that I don’t need. But if you have lots of digits and space is tight, you might look at enhancing this.

Points of interest

I suppose that anyone examining my source code will wonder why in the world my table of bar width has two extra columns. In any sane universe, there should be six columns rather than eight. This was a compromise to allow for the oddball STOP code, which has seven bars rather than six. I could have implemented a special case for just this code, but that was too distasteful.

Instead, I added extra zero-width columns to everything else, making the data equivalent in all cases. For every bar that comes up with a zero width, nothing is output, so nothing is harmed.

Of course, the choice between six or eight columns just begs the question: why not seven? This is to accommodate an optimization in the rendering code. By pre-initializing the entire image to white, I can avoid needing to draw the white bars. Thus, I grab bar widths in groups of two. The first one is the black one, and I draw that normally (unless its width is zero). The second one is white, but there’s white already there, so I can just skip the area that would have occupied.

If anyone’s keeping score, this is my second attempt at truly Test-Driven Development. On the whole, I think this worked out pretty well. Especially, at the lower levels of code, I’m pretty confident of the code. However, the highest level — where the output is just an Image — seemed impractical to be tested in this way.

One problem I’ve got with the TDD, though, is code visibility. Optimally, this library should have exactly one publicly-visible class, with one public method. However, my test code forces me to expose all of the lower-level stuff that the end caller should never know about. If TDD in C# has developed a good answer to that, I haven’t yet stumbled upon it.

History

  • 1.0.0.0 – 2006-06-10Initial release.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Referenced by: http://www.codeproject.com/KB/GDI-plus/GenCode128.aspx?msg=2494595

 
2 Comments

Posted by on November 22, 2011 in C#, Window Application

 

Disable Special Keys in Win App C#

Today, when I was planning to write an article on Grid View. I got a message from a very good friend of mine who is asking to disable the special keys(Windows Keys) in his application. When I start researching on it, I was thinking that it can be done using e.KeyChar but unfortunately, it is not showing any information about windows keys.

So in this post I will explain you, how can we disable the special keys (in our case windows keys) in C# Application.

1. Crete a c# windows application project
2. On the code behind of your default form add the following references

   1: using System.Diagnostics;
   2: using System.Runtime.InteropServices;

3. Now before the constructor of your form place the following code.

   1: // Structure contain information about low-level keyboard input event
   2: [StructLayout(LayoutKind.Sequential)]
   3: private struct KBDLLHOOKSTRUCT
   4: {
   5:     public Keys key;
   6:     public int scanCode;
   7:     public int flags;
   8:     public int time;
   9:     public IntPtr extra;
  10: }
  11:  
  12: //System level functions to be used for hook and unhook keyboard input
  13: private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
  14: [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  15: private static extern IntPtr SetWindowsHookEx(int id, LowLevelKeyboardProc callback, IntPtr hMod, uint dwThreadId);
  16: [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  17: private static extern bool UnhookWindowsHookEx(IntPtr hook);
  18: [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  19: private static extern IntPtr CallNextHookEx(IntPtr hook, int nCode, IntPtr wp, IntPtr lp);
  20: [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  21: private static extern IntPtr GetModuleHandle(string name);
  22: [DllImport("user32.dll", CharSet = CharSet.Auto)]
  23: private static extern short GetAsyncKeyState(Keys key);
  24:  
  25:  
  26: //Declaring Global objects
  27: private IntPtr ptrHook;
  28: private LowLevelKeyboardProc objKeyboardProcess;

4. Now add the following code on your constructor.

   1: public Form1()
   2: {
   3:     ProcessModule objCurrentModule = Process.GetCurrentProcess().MainModule; //Get Current Module
   4:     objKeyboardProcess = new LowLevelKeyboardProc(captureKey); //Assign callback function each time keyboard process
   5:     ptrHook = SetWindowsHookEx(13, objKeyboardProcess, GetModuleHandle(objCurrentModule.ModuleName), 0); //Setting Hook of Keyboard Process for current module
   6:  
   7:  
   8:     InitializeComponent();
   9: }

5. Now Implement the callback function

   1: private IntPtr captureKey(int nCode, IntPtr wp, IntPtr lp)
   2: {
   3:     if (nCode >= 0)
   4:     {
   5:         KBDLLHOOKSTRUCT objKeyInfo = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lp, typeof(KBDLLHOOKSTRUCT));
   6:  
   7:         if (objKeyInfo.key == Keys.RWin || objKeyInfo.key == Keys.LWin) // Disabling Windows keys
   8:         {
   9:             return (IntPtr)1;
  10:         }
  11:     }
  12:     return CallNextHookEx(ptrHook, nCode, wp, lp);
  13: }

6. Now go to your designer class and replace your dispose method.

   1: /// <summary>
   2: /// Clean up any resources being used.
   3: /// </summary>
   4: /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
   5: protected override void Dispose(bool disposing)
   6: {
   7:     if (disposing && (components != null))
   8:     {
   9:  
  10:         components.Dispose();
  11:     }
  12:     if (ptrHook != IntPtr.Zero)
  13:     {
  14:         UnhookWindowsHookEx(ptrHook);
  15:         ptrHook = IntPtr.Zero;
  16:     }
  17:     base.Dispose(disposing);
  18: }

So, in this way we can stop the windows key operation till your application is running.You can find the VS 2008 Source code here.

Referenced by: http://geekswithblogs.net/aghausman/archive/2009/04/26/disable-special-keys-in-win-app-c.aspx
// ------------ Code ----------------------- 
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace WindowsKeyPressed 
{
    public partial class Form1 : Form
    {
        // Structure contain information about low-level keyboard input event
        [StructLayout(LayoutKind.Sequential)]
        private struct KBDLLHOOKSTRUCT
        {
            public Keys key;
            public int scanCode;
            public int flags;
            public int time;
            public IntPtr extra;
        }

        //System level functions to be used for hook and unhook keyboard input
        private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int id, LowLevelKeyboardProc callback, IntPtr hMod, uint dwThreadId);
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool UnhookWindowsHookEx(IntPtr hook);
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hook, int nCode, IntPtr wp, IntPtr lp);
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string name);
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern short GetAsyncKeyState(Keys key);


        //Declaring Global objects
        private IntPtr ptrHook;
        private LowLevelKeyboardProc objKeyboardProcess; 

        public Form1()
        {
            ProcessModule objCurrentModule = Process.GetCurrentProcess().MainModule;
            objKeyboardProcess = new LowLevelKeyboardProc(captureKey);
            ptrHook = SetWindowsHookEx(13, objKeyboardProcess, GetModuleHandle(objCurrentModule.ModuleName), 0);


            InitializeComponent();
        }

        private IntPtr captureKey(int nCode, IntPtr wp, IntPtr lp)
        {
            if (nCode >= 0)
            {
                KBDLLHOOKSTRUCT objKeyInfo = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lp, typeof(KBDLLHOOKSTRUCT));

                if (objKeyInfo.key == Keys.RWin || objKeyInfo.key == Keys.LWin) // Disabling Windows keys
                {
                    return (IntPtr)1;
                }
            }
            return CallNextHookEx(ptrHook, nCode, wp, lp);
        }


        
        private void Form1_KeyPress(object sender, KeyPressEventArgs e)
        {
            MessageBox.Show(e.KeyChar.ToString());
        }


    }

For Disable Art + Tab

// Structure contain information about low-level keyboard input event 
    [StructLayout(LayoutKind.Sequential)]
    private struct KBDLLHOOKSTRUCT
    {
        public Keys key;
        public int scanCode;
        public int flags;
        public int time;
        public IntPtr extra;
    }
    //System level functions to be used for hook and unhook keyboard input  
    private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int id, LowLevelKeyboardProc callback, IntPtr hMod, uint dwThreadId);
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool UnhookWindowsHookEx(IntPtr hook);
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hook, int nCode, IntPtr wp, IntPtr lp);
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string name);
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern short GetAsyncKeyState(Keys key);
    //Declaring Global objects     
    private IntPtr ptrHook;
    private LowLevelKeyboardProc objKeyboardProcess;

    private IntPtr captureKey(int nCode, IntPtr wp, IntPtr lp)
    {
        if (nCode >= 0)
        {
            KBDLLHOOKSTRUCT objKeyInfo = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lp, typeof(KBDLLHOOKSTRUCT));

            // Disabling Windows keys 

            if (objKeyInfo.key == Keys.RWin || objKeyInfo.key == Keys.LWin || objKeyInfo.key == Keys.Tab && HasAltModifier(objKeyInfo.flags) || objKeyInfo.key == Keys.Escape && (ModifierKeys & Keys.Control) == Keys.Control)     
            {
                return (IntPtr)1; // if 0 is returned then All the above keys will be enabled
            }
        }
        return CallNextHookEx(ptrHook, nCode, wp, lp);
    }

    bool HasAltModifier(int flags)
    {
        return (flags & 0x20) == 0x20;
    }

    /* Code to Disable WinKey, Alt+Tab, Ctrl+Esc Ends Here */

http://stackoverflow.com/questions/3213606/how-to-suppress-task-switch-keys-winkey-alt-tab-alt-esc-ctrl-esc-using-low
 
8 Comments

Posted by on August 30, 2011 in C#, Window Application