RSS

Category Archives: 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

 
Leave a comment

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());
        }


    }

 
4 Comments

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

 

AutoComplete TextBox in C#

Most of the developers are familiar with the auto completion text feature available in browsers, search controls and other controls. The auto completion feature is when you start typing some characters in a control, the matching data is loaded automatically for you.

In Visual Studio 2005, some of the controls support this feature including the ComboBox and the TextBox controls. By using these features, we can build Internet Explorer like auto completion functionality in our Windows Forms applications.

Now, we can have a combo box that completes URLs as soon as you type any character. For example, in Figure 1, I typed “c-s” and I see all the URLs starting with “c-s”.

AutoCompleteImg1.gif

Figure 1. Auto Completion in a ComboBox

The AutoCompleteSource and AutoCompleteMode properties of the TextBox and ComboBox controls allow developers to provide automatic completion text feature. You can set both of these properties at design-time as well as at run-time. If you click on AutoCompleteSource drop down, you will see all the options in the drop-down list. See Figure 2.

AutoCompleteImg2.GIF

Figure 2. AutoCompleteSource options

Figure 3 shows AutoCompleteMode options.

AutoCompleteImg3.GIF

Figure 3. AutoCompleteMode options

You can also set these properties at run-time using the following code:

comboBox1.AutoCompleteSource = AutoCompleteSource.AllSystemSources;
comboBox1.AutoCompleteMode = 
AutoCompleteMode.SuggestAppend;

The AutoCompleteSource Enumeration has following members:

  • AllSystemResources - Specifies the equivalent of FileSystem and AllUrl as the source. This is the default value when AutoCompleteMode has been set to a value other than the default.
  • AllUrl - Specifies the equivalent of HistoryList and RecentlyUsedList as the source.
  • CustomSource - Specifies strings from a built-in AutoCompleteStringCollection as the source.
  • FileSystem - Specifies the file system as the source.
  • FileSystemDirectories - Specifies that only directory names and not file names will be automatically completed.
  • HistoryList - Includes the Uniform Resource Locators (URLs) in the history list.
  • ListItems - Specifies that the items of the ComboBox represent the source.
  • None - Specifies that no AutoCompleteSource is currently in use. This is the default value of AutoCompleteSource.
  • RecentlyUsedList - Includes the Uniform Resource Locators (URLs) in the list of those URLs most recently used.

The AutoCompleteMode enumeration has following members:

  • Append - Appends the remainder of the most likely candidate string to the existing characters, highlighting the appended characters.
  • None - Disables the automatic completion feature for the ComboBox and TextBox controls.
  • Suggest - Displays the auxiliary drop-down list associated with the edit control. This drop-down is populated with one or more suggested completion strings.
  • SuggestAppend - Applies both Suggest and Append options.

Loading Custom Source

We can also specify a custom source from where the listing will be loaded. If you click on the AutoCompleteCustomSource property, it will open the String Collection Editor, where we can add our strings. For example, I add following strings to the strings list. See Figure 4.

AutoCompleteImg4.GIF

Figure 4. Custom Source strings

Now we need to set AutoCompleteSource to CustomSource:

comboBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;

And when I run and type “v” in the combo box, I see VB.NET Heaven. See Figure 5.

AutoCompleteImg5.GIF

Figure 5. Custom Source listing

We can also create AutoCompleteStringCollection programmatically. The following code creates an AutoCompleteStringCollection, adds strings to the collection, and sets it to the AutoCompleteCustomSource of the ComboBox.

// AutoCompleteStringCollection
AutoCompleteStringCollection data = new AutoCompleteStringCollection();
data.Add(
“Mahesh Chand”);
data.Add(
“Mac Jocky”);
data.Add(
“Millan Peter”);
comboBox1.AutoCompleteCustomSource = data;

Now running the sample and typing “m” in the ComboBox loads the data as shown in Figure 6.

AutoCompleteImg6.GIF 

Figure 6. Loading custom data

Summary

The AutoComplete feature of ComboBox and TextBox controls allow us to set the auto complete text feature. In this article, we saw how to use this feature in our application at design-time as well as at run-time.

Referenced by: http://www.c-sharpcorner.com/UploadFile/mahesh/AutoCompletion02012006113508AM/AutoCompletion.aspx

 
Leave a comment

Posted by on July 5, 2011 in C#, Window Application

 

How to get into LogIn form – if there isnt any key press in my C#

I have Login form and Main form in my C# WinForm program.

When I’m in the Main form and the user doesn’t press any key or move the mouse for 5 minutes – I want to go to Login form.

This example will raise message when user is not active for 5 minutes.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
static class Program
{

private static Timer _idleTimer;

[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

_idleTimer = new Timer();
_idleTimer.Tick += new EventHandler(_idleTimer_Tick);
_idleTimer.Interval = (5 * 60) * 1000; // (5 minutes * seconds) * milliseconds

Application.AddMessageFilter(new MouseMessageFilter(UserIsActive));
Application.AddMessageFilter(new KeyboardMessageFilter(UserIsActive));

Application.Run(new Form1());
}

static void _idleTimer_Tick(object sender, EventArgs e)
{
MessageBox.Show("You are idle for " + _idleTimer.Interval.ToString() + " milliseconds");
}

static void UserIsActive(object sender, EventArgs e)
{
_idleTimer.Stop();
_idleTimer.Start();
}

public class MouseMessageFilter : IMessageFilter
{
private EventHandler _callback;

public MouseMessageFilter(EventHandler callback)
{
_callback = callback;
}

private const int WM_MOUSEMOVE = 0x0200;

public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_MOUSEMOVE)
{
_callback(null, null);
}

return false;
}
}

private class KeyboardMessageFilter : IMessageFilter
{
private EventHandler _callback;

public KeyboardMessageFilter(EventHandler callback)
{
_callback = callback;
}

const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x0101;
const int WM_SYSKEYDOWN = 0x104;
const int WM_SYSKEYUP = 0x0105;

#region IMessageFilter Members

public bool PreFilterMessage(ref Message m)
{
if ((m.Msg == WM_KEYDOWN) || (m.Msg == WM_SYSKEYDOWN))
{
_callback(null, null);
}

if ((m.Msg == WM_KEYUP) || (m.Msg == WM_SYSKEYUP))
{
_callback(null, null);
}

return false;
}

#endregion
}

}
}

Referenced by: http://stackoverflow.com/questions/5477939/how-to-get-into-login-form-if-there-isnt-any-key-press-in-my-c-program

 
Leave a comment

Posted by on June 6, 2011 in C#, Window Application

 

Dynamic Add Data into TreeView in C#

This technique apply for nested data store on relational dbms, for examples:

Table1
+——–+——–+———-+
|  ID     |  Name  | ParentID |
+——–+——–+———-+
|  1     |  A     | 0        |
|  2     |  B     | 0        |
|  3     |  C     | 0        |
|  4     |  a     | 1        |
|  5     |  b     | 1        |
|  6     |  c     | 2        |
|  7     |  d     | 3        |
|  8     |  e     | 3        |
+——–+——–+———-+

And we want to show in Treeview control as:

TreeviewControl
+–
|-A-
|-a
|-b
|
|-B-
|-c
|
|-C-
|-d
|-e

So we do not need to use [Loop] to insert sub tree in to other tree.

IEnumerable<Table1> dataCollection =  // From table [Table1] “in Linq code”;

foreach(var record in dataCollection)
{
if(record.ParentID == 0)
{
TreeviewControl.Nodes.Add(record.ID.toString(), record.Name);
}
else
{
TreeNode[] tn = TreeviewControl.Nodes.Find(record.ParentID.toString(), true);
tn[0].Nodes.Add(record.ID.toString(), record.Name);
}

 
Leave a comment

Posted by on May 27, 2011 in C#, Window Application

 

Treeview Control – chek child if parent is checked for C#

private void TreeView1_AfterCheck(object sender, System.Windows.Forms.TreeViewEventArgs e)
{
	// For Select all to sub tree
	TreeNode parent_node = e.Node;
	bool is_checked = parent_node.Checked;
	for (int i = 0; i <= e.Node.Nodes.Count - 1; i++) {
		SetSubtreeChecked(parent_node.Nodes(i), is_checked);
	}
	bool blnUncheck = false;

	//---------------------------------------------------

	//Check to see if a parent node exists.

	if ((e.Node.Parent != null)) {
		//Loop through the child nodes.
		foreach (TreeNode child in e.Node.Parent.Nodes) {
			//Check to see if the current node is unchecked.
			if (child.Checked == true) {
				//Set the variable.
				blnUncheck = true;
			}
		}
		//Check the variable.
		if (blnUncheck == false) {
			//Check the parent node.
			e.Node.Parent.Checked = false;
		} else {
			//Uncheck the parent node.
			e.Node.Parent.Checked = true;
		}
	}
}
//'========================================================
//'          For Tree view Items Validation
//'========================================================
private void SetSubtreeChecked(TreeNode parent_node, bool is_checked)
{
	// Set the parent's Checked value.
	parent_node.Checked = is_checked;
	// Set the child nodes' Checked values.
	for (int i = 0; i <= parent_node.Nodes.Count - 1; i++) {
		SetSubtreeChecked(parent_node.Nodes(i), is_checked);
	}
}

Referenced by: http://social.msdn.microsoft.com/Forums/en-US/vssmartdevicesvbcs/thread/f4269ae8-f788-4637-a454-df0f6bf05db5/

 
Leave a comment

Posted by on May 27, 2011 in C#, Window Application

 

How can I validate input to the edit control of a cell in a DataGridView?

<code>private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
//Remove any KeyPress events already attached
e.Control.KeyPress -= new KeyPressEventHandler(FirstEditingControl_KeyPress);
e.Control.KeyPress -= new KeyPressEventHandler(SecondEditingControl_KeyPress);

//Choose event to wire based on control type
if (e.Control is NumericTextBox)
{
e.Control.KeyPress += new KeyPressEventHandler(FirstEditingControl_KeyPress);
} else if (e.Control is CurrencyTextBox)
{
e.Control.KeyPress += new KeyPressEventHandler(SecondEditingControl_KeyPress);
}
}</code>

Referenced by: http://stackoverflow.com/questions/2651105/how-can-i-validate-input-to-the-edit-control-of-a-cell-in-a-datagridview

 
Leave a comment

Posted by on May 20, 2011 in C#, Window Application

 

Copy file to remote computer using remote admin credentials

Correct me if I’m wrong, but you can use LogonUser to impersonate a local group also not only domain accounts.
by: Shay Erlichmen

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security.Permissions;
public class Form1
{
	[DllImport("advapi32.DLL", SetLastError = true)]
	public static extern int LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
	private void Button1_Click(System.Object sender, System.EventArgs e)
	{
		IntPtr admin_token = default(IntPtr);
		WindowsIdentity wid_current = WindowsIdentity.GetCurrent();
		WindowsIdentity wid_admin = null;
		WindowsImpersonationContext wic = null;
		try {
			MessageBox.Show("Copying file...");
			if (LogonUser("Local Admin name", "Local computer name", "pwd", 9, 0, ref admin_token) != 0) {
				wid_admin = new WindowsIdentity(admin_token);
				wic = wid_admin.Impersonate();
				System.IO.File.Copy("C:\\right.bmp", "\\\\157.60.113.28\\testnew\\right.bmp", true);
				MessageBox.Show("Copy succeeded");
			} else {
				MessageBox.Show("Copy Failed");
			}
		} catch (System.Exception se) {
			int ret = Marshal.GetLastWin32Error();
			MessageBox.Show(ret.ToString(), "Error code: " + ret.ToString());
			MessageBox.Show(se.Message);
		} finally {
			if (wic != null) {
				wic.Undo();
			}
		}
	}
}

Referenced by: http://stackoverflow.com/questions/766033/copy-file-to-remote-computer-using-remote-admin-credentials

 
1 Comment

Posted by on May 6, 2011 in C#, Window Application

 
 
Follow

Get every new post delivered to your Inbox.