Archive

Posts Tagged ‘Windows Forms’

WebCam in your applications using C#

November 16th, 2009 Anuraj P No comments

In the current project I am working I got a chance to implement web cam image capture. There is two different ways to do this in C#.

  1. Using WIA Sdk – It is library coming with Windows. And you can download this COM library from Microsoft site. But the problem of this approch is sometime the cam is not supported by WIA and you will get an exception like “Exception from HRESULT: Ox80210015″.
  2. Using AVICAP32 library – In this method we are invoking methods from avicap32.dll, and interacting with Web Cam. Here is a simple implementation, which will connect with WebCam, show Preview and Save the Image.

    Implementation

    Add a Picturebox to a Form, which will display the Preview. And write the following code.

    
    [DllImport("user32", EntryPoint = "SendMessage")]
    public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
    
    [DllImport("avicap32.dll", EntryPoint = "capCreateCaptureWindowA")]
    public static extern int capCreateCaptureWindowA(string lpszWindowName, int dwStyle, int X, int Y, int nWidth, int nHeight, int hwndParent, int nID);
    
    public const int WM_USER = 1024;
    public const int WM_CAP_CONNECT = 1034;
    public const int WM_CAP_DISCONNECT = 1035;
    public const int WM_CAP_GET_FRAME = 1084;
    public const int WM_CAP_COPY = 1054;
    
    public const int WS_CHILD = 0x40000000;
    public const int WS_VISIBLE = 0x10000000;
    
    public const int WM_CAP_START = WM_USER;
    public const int WM_CAP_SET_SCALE = WM_CAP_START + 53;
    public const int WM_CAP_SET_PREVIEWRATE = WM_CAP_START + 52;
    public const int WM_CAP_SET_PREVIEW = WM_CAP_START + 50;
    
    private int mCapHwnd = 0;	//Handle
    
    private void Connect()
    {
    
    	mCapHwnd = capCreateCaptureWindowA("WebCap", WS_VISIBLE | WS_CHILD, 0, 0, 350, 350, this.pictureBox.Handle.ToInt32(), 0);
    	if (SendMessage(mCapHwnd, WM_CAP_CONNECT, 0, 0) > 0)	//This will make sure the device is connected to the System
    	{
    		SendMessage(mCapHwnd, WM_CAP_SET_PREVIEWRATE, 30, 0);
    		SendMessage(mCapHwnd, WM_CAP_SET_PREVIEW, 1, 0);
    	}
    	else
    	{
    		MessageBox.Show("No device found!");
    	}
    }
    
    private void TakePicture()
    {
    
    	SendMessage(mCapHwnd, WM_CAP_GET_FRAME, 0, 0);
    	SendMessage(mCapHwnd, WM_CAP_COPY, 0, 0);
    	//Saving the Clipborad Data
    	using (SaveFileDialog dlg = new SaveFileDialog())
    	{
    		dlg.Filter = "JPG Images|*.jpg";
    		dlg.OverwritePrompt = true;
    		dlg.ValidateNames = true;
    		dlg.DefaultExt = "JPG";
    		if (dlg.ShowDialog(this) == DialogResult.OK)
    		{
    			Clipboard.GetImage().Save(dlg.FileName, ImageFormat.Jpeg);
    		}
    	}
    }
    private void Disconnect()
    {
                SendMessage(mCapHwnd, WM_CAP_DISCONNECT, mCapHwnd, 0);
    }
    

    On the Form_Load event, call the Connect() method, which will connect to the Web cam and display a Preview in the Picturebox. I have added a button to take picture and on the Click event of the button, call the TakePicture() method, which will grabs the current frame from Web Cam and copy it to the Clipboard, and using the FileSaveDialog it is saving to the FileSystem. On the Form_Closing() event, call the Disconnect() method, which disconnects the cam. Happy Programming :)

  3. You can download WIA library from : http://www.microsoft.com/downloads/details.aspx?familyid=a332a77a-01b8-4de6-91c2-b7ea32537e29.

Post data using HttpWebRequest in C#

November 10th, 2009 Anuraj P No comments

While working around twitter or any other REST API services, you may require to do a post request to web server. If you are using .net can do this either using WebClient class or using HttpWebRequest class. Both these classes exists in System.Net namespace. I am using HttpWebRequest here because HttpWebRequest gives you more fine grained control over your request. WebClient does not. Also webclient encapsulates most of the stuff for you. HttpWebRequest allows to send headers or other customizations.

You can also invoke Web Services using HttpWebRequest class.

//Creating the Web Request.
HttpWebRequest httpWebRequest = HttpWebRequest.Create("http://localhost/DemoApp/Default.aspx") as HttpWebRequest;
//Specifing the Method
httpWebRequest.Method = "POST";
//Data to Post to the Page, itis key value pairs; separated by "&"
string data = "Username=username&password=password";
//Setting the content type, it is required, otherwise it will not work.
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
//Getting the request stream and writing the post data
using (StreamWriter sw = new StreamWriter(httpWebRequest.GetRequestStream()))
{
    sw.Write(data);
}
//Getting the Respose and reading the result.
HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
using (StreamReader sr = new StreamReader(httpWebResponse.GetResponseStream()))
{
    MessageBox.Show(sr.ReadToEnd());
}

It will show some HTML content in the Message box.

You can also access or post data to .net web services. For sending data to webservices, you need to change the URL like following

http://www.dotnetthoughts.net/sample.asmx/HelloWorld.

where HelloWorld is the Web Method name to invoke. It will return an XML after successful operation.

Implementing Close button in Tab Pages

November 8th, 2009 Anuraj P No comments

Long back, when I worked on Windows Application, my client asked me to change the UI, instead of using MDI, he want to use SDI. And for multiple Windows, suggested Tab Control, like the new Web Browsers. Fortunately he dropped the idea of SDI later and I continue to use MDI. But few days ago I got a question from a dotnet forum, how can we create close button for the Tab Pages in Tab Control. While searching I got lot of implementations, later I implemented it in my own way. In the implementations I found, they are inheriting from Tab Control, in this implementation, I implemented in such way that it can be applied for an existing Tab Control.

  1. Set the DrawMode property of the Tab Control to OwnerDrawFixed. This property is decides whether system or developer painting the captions.
  2. Add the code in the DrawItem event of the Tab Control – This event will be invoked for painting each Tab Page.
  3. //This code will render a "x" mark at the end of the Tab caption.
    e.Graphics.DrawString("x", e.Font, Brushes.Black, e.Bounds.Right - 15, e.Bounds.Top + 4);
    e.Graphics.DrawString(this.tabControl1.TabPages[e.Index].Text, e.Font, Brushes.Black, e.Bounds.Left + 12, e.Bounds.Top + 4);
    e.DrawFocusRectangle();
    
  4. Now for close button action, we need to add the following code to the MouseDown event of the Tab Control.
  5. //Looping through the controls.
    for (int i = 0; i < this.tabControl1.TabPages.Count; i++)
    {
        Rectangle r = tabControl1.GetTabRect(i);
       //Getting the position of the "x" mark.
        Rectangle closeButton = new Rectangle(r.Right - 15, r.Top + 4, 9, 7);
        if (closeButton.Contains(e.Location))
        {
            if (MessageBox.Show("Would you like to Close this Tab?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                this.tabControl1.TabPages.RemoveAt(i);
                break;
            }
        }
    }
    

Here is the screenshot, of the implementation, running on my machine.

Close Button in Tab Pages

Close Button in Tab Pages

WPF interoperability with Windows Forms

November 2nd, 2009 Anuraj P No comments

In October 24th 2009, I got a chance to attend MS Community Techdays at Trivandrum. One of the session was WPF interoperability with Windows Forms. By using this we can use WPF controls in Classic Windows based applications. For this you require a special control called “ElementHost“, if you developed any Windows based application in VS 2008, this control will be available under WPF interoperability tab. If you add this control to a Windows Form, Visual Studio will automatically updates the References list. It will add few more references like PresentationCore, PresentationFrameWork, UIAutomationProvider, WindowsBase, WindowsFormsIntegration. Then you can add a WPF User Control to a Windows Form.

  1. Create a Windows Application Project.
  2. Right Click on the Project Node in the solution explorer, select Add New Item, and Select User Control(WPF) from Add New Item Dialog.
  3. In the User Contol I wrote some code to change the Color on MouseMove and I wrote the click event in the Codebehind.
  4. XAML Code

    <Grid>
        <Grid.Resources>
            <Style TargetType="Button" x:Key="CustomButton">
                <Setter Property="FontSize" Value="15" />
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="FontSize" Value="20" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Grid.Resources>
        <Button Style="{StaticResource CustomButton}"
                Content="Hello World"
                Click="Button_Click">
        </Button>
    </Grid>
    

    Code behind – C#

    private void Button_Click(object sender, RoutedEventArgs e)
    {
    	MessageBox.Show("WPF UserControl Event");
    }
    
  5. Build the Project.
  6. Drag and Drop, ElementHost control from WPF interoperability tab.
  7. You can Set the host the WPF usercontrol either by selecting Select Host Content from Smart Menu, or by Setting the Child Property in the Property List. (The control will be populated in the List only if you build the application, after you added the control.)
  8. You can also do it in runtime by setting Child Property of the Element Host control.
  9. private void Form1_Load(object sender, EventArgs e)
    {
            SampleWPFCtrl ctrl1 = new SampleWPFCtrl();
                this.elementHost1.Child = ctrl1;
    }
    
    WPF Usercontol Control in Windows Form

    WPF Usercontol Control in Windows Form

    Happy Coding :)

TreeView Population without recursive function

October 20th, 2009 Anuraj P No comments

If you want to display hierarchical data in a Treeview normally we are using recursion. I was looking for code which helps to avoid recursion using a Single query. But that code was using VB.Net and it was using a class called “Collection”, which is not available in C#. So I was looking for a compatable code in C# for long time and today I got the chance to re-write it using C#, but I am using Lamda expressions for this.

Here is the Table structure I want to display in Treeview


CREATE TABLE [dbo].[tblEmployees](
[EmployeeId] [int] IDENTITY(1,1) NOT NULL,
[EmployeeName] [nvarchar](50) NOT NULL,
[Parent] [int] NOT NULL)

And I inserted following Data in it.

Table Data

Table Data

And the Stored Procedure for getting employees using Common Table Expressions.

-- usp_GetEmployees
CREATE PROCEDURE [dbo].[usp_GetEmployees]
AS
BEGIN
	WITH SimpleRecursive AS
	(SELECT EmployeeName, EmployeeId, Parent, 0 AS Depth FROM dbo.tblEmployees
	WHERE (EmployeeId IN(SELECT EmployeeId FROM dbo.tblEmployees AS Recursion1
	WHERE (Parent = 0)))
	UNION ALL
	SELECT P.EmployeeName, P.EmployeeId,P.Parent, A.Depth + 1 AS Depth
	FROM dbo.tblEmployees AS P INNER JOIN SimpleRecursive AS A ON A.EmployeeId = P.Parent)
	SELECT EmployeeName, EmployeeId, CONVERT(INT, Parent) AS Parent, Depth
	FROM SimpleRecursive AS SimpleRecursive_1
	ORDER BY Depth
END

And the code in C# which adding nodes to Treeview.

private void PopulateTreeview()
{
    this.tvEmployees.Nodes.Clear();
    Employees employees = new Employees();
    using (SqlConnection connection = new SqlConnection(@"Server=.\SQLEXPRESS; User Id=SQLUser;Password=SQLPassword;Database=Database"))
    {
        connection.Open();
        using (SqlCommand command = new SqlCommand("usp_GetEmployees", connection))
        {
            command.CommandType = System.Data.CommandType.StoredProcedure;
            SqlDataReader reader = command.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
            while (reader.Read())
            {
                employees.Add(new Employees.Employee()
                {
                    Depth = int.Parse(reader["depth"].ToString()),
                    EmployeeId = int.Parse(reader["EmployeeId"].ToString()),
                    Parent = int.Parse(reader["Parent"].ToString()),
                    EmployeeName = reader["EmployeeName"].ToString(),
                });
            }
        }
    }

    foreach (Employees.Employee employee in employees)
    {
        Employees.Employee parentEmp = employees.Find(o => o.EmployeeId == employee.Parent);
        if (parentEmp != null)
        {
            this.tvEmployees.Nodes.Find(parentEmp.EmployeeId.ToString(), true)[0].Nodes.Add(employee.EmployeeId.ToString(), employee.EmployeeName);
        }
        else
        {
            this.tvEmployees.Nodes.Add(employee.EmployeeId.ToString(), employee.EmployeeName);
        }
    }
    this.tvEmployees.ExpandAll();
}

And the employees class

public class Employees : List<Employees.Employee>
{
    public class Employee
    {
        public int EmployeeId
        {
            get;
            set;
        }
        public string EmployeeName
        {
            get;
            set;
        }
        public int Parent
        {
            get;
            set;
        }
        public int Depth
        {
            get;
            set;
        }
    }
}

And here is the screenshot

Treeview Demo - Screenshot

Treeview Demo - Screenshot


Thanks to Aneesh and Anas for their valuable comments.
Happy Programming :)

Application development using Gtk# in .Net

October 17th, 2009 Anuraj P No comments

When I started my software development career, I got introduced to some cool tools for GUI application development in Linux. I was using Glade and the library was Gtk. Then later I become a MS fan and started working on ASP, VB and .Net. Yesterday I got a chance to download Mono and Monodevelop. And the Gtk for Windows and .Net called Gtk#. I explored in Mono Develop(I was downloaded MonoDevelop-2.2 beta 2) a little, but it was crashed for me two time. :( Then I started using Gtk# in VC# Express. And I created a simple Text File Viewer using C#, with Gtk# for UI. Most of the things in Gtk# is pretty different from .Net Windows Forms development. And I like the concept to in built support for predefined MenuItems, Icons etc. I think MS took the idea of commands in WPF from this.

I created a Windows Application Project and Added reference of the following libraries

atk-sharp.dll
gdk-sharp.dll
glade-sharp.dll
glib-sharp.dll
gtk-dotnet.dll
gtk-sharp.dll

And I deleted the Form1. And modified the Program.cs; the Program.cs

namespace HelloGtk
{
    using System;
    using Gtk;

    public class Program
    {
        private MainWindow mainWindow = null;

        public Program()
        {
            Application.Init();
            mainWindow = new MainWindow();
            Application.Run();
        }

        static void Main()
        {
            new Program();
            return;
        }
    }
}

And the added a class MainWindow.cs, and wrote the code

namespace HelloGtk
{
    using Gtk;
    using System.IO;

    public class MainWindow : Gtk.Window
    {
        private string title = "Text File Viewer";
        private VBox vbox;
        private MenuBar menubar;
        private Statusbar statusbar;
        private TextView textView;
        private ScrolledWindow scrolledWindow;
        private AccelGroup accelGroup;
        private Toolbar toolbar;
        public MainWindow()
            : base("Text File Viewer")
        {
            this.DefaultSize = new Gdk.Size(600, 500);
            this.DeleteEvent += new DeleteEventHandler(MainWindow_DeleteEvent);
            this.Build();
        }

        private void MainWindow_DeleteEvent(object o, DeleteEventArgs args)
        {
            Application.Quit();
            args.RetVal = true;
        }

        private void Build()
        {
            this.Title = this.title;
            this.vbox = new VBox(false, 0);
            this.CreateMenubar();
            this.vbox.PackStart(this.menubar, false, true, 0);
            this.toolbar = new Toolbar();
            this.CreateToolbar();
            this.vbox.PackStart(this.toolbar, false, true, 0);
            this.textView = new TextView();
            this.textView.Editable = false;
            this.textView.WrapMode = WrapMode.Word;
            this.scrolledWindow = new ScrolledWindow();
            this.scrolledWindow.SetPolicy(PolicyType.Automatic, PolicyType.Automatic);
            this.scrolledWindow.Add(this.textView);
            this.vbox.PackStart(this.scrolledWindow, true, true, 0);
            this.statusbar = new Statusbar();
            this.vbox.PackStart(this.statusbar, false, true, 0);
            this.Add(this.vbox);
            this.ShowAll();
        }
        private void CreateToolbar()
        {
            ToolButton OpenToolBarBtn = new ToolButton("gtk-open");
            OpenToolBarBtn.Clicked += this.openMenu_Activated;
            SeparatorToolItem Sep1 = new SeparatorToolItem();
            ToolButton CopyToolBarBtn = new ToolButton("gtk-copy");
            CopyToolBarBtn.Clicked += this.copyMenu_Activated;
            SeparatorToolItem Sep2 = new SeparatorToolItem();
            ToolButton AboutToolBarBtn = new ToolButton("gtk-about");
            AboutToolBarBtn.Clicked += this.aboutMenu_Activated;

            this.toolbar.Add(OpenToolBarBtn);
            this.toolbar.Add(Sep1);
            this.toolbar.Add(CopyToolBarBtn);
            this.toolbar.Add(Sep2);
            this.toolbar.Add(AboutToolBarBtn);
        }

        private void CreateMenubar()
        {
            this.accelGroup = new AccelGroup();
            this.menubar = new MenuBar();
            MenuItem fileMenu = new MenuItem("_File");
            MenuItem editMenu = new MenuItem("_Edit");
            MenuItem helpMenu = new MenuItem("_Help");
            helpMenu.RightJustified = true;

            Menu fileSubMenu = new Menu();
            TearoffMenuItem fileMenuTearOff = new TearoffMenuItem();
            ImageMenuItem openMenu = new ImageMenuItem("gtk-open", accelGroup);
            openMenu.Activated += new System.EventHandler(openMenu_Activated);
            SeparatorMenuItem fileMenuSep = new SeparatorMenuItem();
            ImageMenuItem exitMenu = new ImageMenuItem("gtk-quit", accelGroup);
            exitMenu.Activated += new System.EventHandler(exitMenu_Activated);
            fileSubMenu.Add(fileMenuTearOff);
            fileSubMenu.Add(openMenu);
            fileSubMenu.Add(fileMenuSep);
            fileSubMenu.Add(exitMenu);
            fileMenu.Submenu = fileSubMenu;

            Menu editSubMenu = new Menu();
            ImageMenuItem copyMenu = new ImageMenuItem("gtk-copy", accelGroup);
            copyMenu.Activated += new System.EventHandler(copyMenu_Activated);
            TearoffMenuItem editMenuTearOff = new TearoffMenuItem();
            editSubMenu.Add(editMenuTearOff);
            editSubMenu.Add(copyMenu);
            editMenu.Submenu = editSubMenu;

            Menu helpSubMenu = new Menu();
            ImageMenuItem aboutMenu = new ImageMenuItem("gtk-about", accelGroup);
            TearoffMenuItem helpMenuTearOff = new TearoffMenuItem();
            helpSubMenu.Add(helpMenuTearOff);
            helpSubMenu.Add(aboutMenu);
            aboutMenu.Activated += new System.EventHandler(aboutMenu_Activated);
            helpMenu.Submenu = helpSubMenu;

            this.menubar.Add(fileMenu);
            this.menubar.Add(editMenu);
            this.menubar.Add(helpMenu);
        }

        void aboutMenu_Activated(object sender, System.EventArgs e)
        {
            using (Dialog dialog = new MessageDialog(this,
                                  DialogFlags.Modal | DialogFlags.DestroyWithParent,
                                  MessageType.Info,
                                  ButtonsType.Ok,
                                  "Text File Viewer - A simple text file viewer using gtk#\nDeveloped by Anuraj\nPowered by dotnetthoughts.net\n\nUnder GNU GPL v2."))
            {
                dialog.Title = "About";
                dialog.Run();
                dialog.Hide();
            }
        }

        private void copyMenu_Activated(object sender, System.EventArgs e)
        {
            Clipboard clipboad = this.textView.GetClipboard(Gdk.Selection.Clipboard);
            this.textView.Buffer.CopyClipboard(clipboad);
        }

        void exitMenu_Activated(object sender, System.EventArgs e)
        {
            Application.Quit();
        }
        FileChooserDialog dlg;
        private void openMenu_Activated(object sender, System.EventArgs e)
        {
            dlg =
                new FileChooserDialog("Select Text File", this, FileChooserAction.Open, "");
            dlg.AddButton("Open File", ResponseType.Ok);
            dlg.AddButton("Cancel", ResponseType.Cancel);

            FileFilter filter = new FileFilter();
            filter.AddPattern("*.txt");
            filter.AddPattern("*.*");
            dlg.Filter = filter;

            dlg.TypeHint = Gdk.WindowTypeHint.Dialog;
            dlg.SelectMultiple = false;
            dlg.WindowPosition = WindowPosition.Center;
            dlg.Parent = this;
            dlg.Modal = true;
            dlg.KeepAbove = true;
            dlg.DestroyWithParent = true;
            dlg.State = StateType.Normal;

            dlg.Response += new ResponseHandler(dlg_Response);
            dlg.DeleteEvent += new DeleteEventHandler(dlg_DeleteEvent);

            dlg.Run();
            dlg.Destroy();

        }

        private void dlg_DeleteEvent(object o, DeleteEventArgs args)
        {
            dlg.Destroy();
        }

        private void dlg_Response(object o, ResponseArgs args)
        {
            if (args.ResponseId == ResponseType.Ok)
            {
                this.Title = string.Format("{0} - {1}", this.title, System.IO.Path.GetFileName(dlg.Filename));
                using (StreamReader reader = new StreamReader(dlg.Filename, true))
                {
                    this.textView.Buffer.Text = reader.ReadToEnd();
                }
            }
            dlg.Destroy();
        }
    }
}

And run the application. Here is the screenshot, Text File Viewer running on my machine.

Text File Viewer using GTK#

Text File Viewer using GTK#