Archive

Archive for November, 2009

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.

Rapid Prototyping – Lessons from the trenches

November 9th, 2009 Anuraj P No comments

One of the session in the Microsoft Community TechDays in Technopark, Trivandrum was Rapid Prototyping – Lessons from the trenches by Uday M. Shankar. In the session the Uday was talking about Microsoft Expression SketchFlow. SketchFlow is a new feature in Expression Blend 3 that enables rapid prototyping of web sites. SketchFlow helps designers, developers, information architects and account managers sketch, wireframe and prototype user experiences and user interfaces.(from Microsoft site). The nice featue I found is option for updating the review from Client or Manager, and it won’t affect your design too.

You can get more information about Sketch Flow from Microsoft site (http://www.microsoft.com/expression/products/SketchFlow_OverView.
aspx). And you can download trial version of Sketch flow from here. http://www.microsoft.com/expression/try-it/Default.aspx?filter=blend3sketchflow.

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

Simple URL Rewriting in ASP.Net with C#

November 3rd, 2009 Anuraj P No comments

If you are developing some content management site or blog, you require clean URLs for better Search engine ranking. Normally in ASP / ASP.Net we used to pass querystrings to pull the data from database.

http://example.com/load_page.aspx?Page=aboutme.aspx

But if you are using query string, it will be difficult for search engine to index. One approch to avoid this issue is creating physical files, and internally pull data from DB. It will act like a template with some information, and on the Page_Load event, it will pull the data from Database and display it in the Page. The main drawbacks of this approch are 1) it will create physical file, 2) the application may require a write permission in the WebServer for creating Files. 3) Difficult to maintain / manage. Another approch and commonly used is URL Rewriting. As the name indicates, it is rewriting an URL, a clean URL request comes to IIS, it will be mapped to another URL, which internally using Query strings. So search engines doesn’t have a problem with indexing the Pages.

http://example.com/aboutme.aspx will be mapped to automatically to http://example.com/load_page.aspx?Page=aboutme.aspx

If you are using IIS7, URL Rewriting module is available from Microsoft, and you can configure it. Here is a simple mapping mechanism which doesn’t require any configuration changes in the IIS, and works with ASP.Net 2.0 onwards.

I wrote the following code in the Global.asax file. And ASP.Net will invoke Application_BeginRequest event for every request, for ASP.Net Pages.

protected void Application_BeginRequest(object sender, EventArgs e)
{
/*
splitting the current URL, you can also do some RegEx checking instead of splitting the whole URL. And it will work only with ASPX extensions.
*/
	string[] urlParts = Context.Request.Url.AbsoluteUri.Split("/".ToCharArray());
	//Taking the Page name
	Context.RewritePath("~/Load_Page.aspx?Page=" + urlParts[urlParts.GetUpperBound(0)]);
}

And the Load_Page.aspx, Page_Load I wrote the code to read the Quey string and display the filename.

protected void Page_Load(object sender, EventArgs e)
{
    string page = Request.QueryString["Page"];
    if (string.IsNullOrEmpty(page))
    {
        Response.Write("Welcome to Home Page");
    }
    else
    {
	//Read the data from DB based on the querystring
        Response.Write("Welcome to " + page);
    }
}

As I mentioned earlier you can modify the code the Application_BeginRequest, and re-write the URL based on RegEx rules.

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 :)