Screen Capture on Windows Phone 7

In some instances when working on projects we would require to take a screen capture of the current screen the user is working on.  I regularly did this on .NET Compact Framework 3.5 (pre Windows Phone 7) and is a little bit of mess because of all the PInvokes involved. 

I decided to create a quick sample app that captures the screen on both platforms to compare the code.  The sample app basically just places the captured screen inside a pictureBox control (NETCF 3.5) or Image control (Silverlight for WP7).  The outer PictureBox/Image control just displays some standard images that come with Windows 7.

Compact Framework 3.5   Silverlight (Windows Phone 7)
image   image

Here is a comparison of capture an image of the current screen on Windows Phone 7 using Silverlight and .NET Compact Framework

.NET Compact Framework

private Bitmap CaptureScreen()
{
    Bitmap b = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
    using (Graphics g = Graphics.FromImage(b))
    {
        IntPtr hdcSrc = IntPtr.Zero;
        IntPtr hdcDest = g.GetHdc();
        try 
        {
            //get the entire window by passing in IntPtr.Zero
            hdcSrc = GetWindowDC(IntPtr.Zero);
            //blit to the graphics object g
            BitBlt(hdcDest, 0, 0, b.Width, b.Height, 
                hdcSrc, 0, 0, SRCCOPY); 
        }
        finally
        {
            //Release any native src hdcs
            if (hdcSrc != IntPtr.Zero)
            {
                ReleaseDC(hdcSrc);
                DeleteDC(hdcSrc);
            }

            //Release the graphics hdc
            g.ReleaseHdc(hdcDest);
        }
    }

    return b;
}

[DllImportAttribute("coredll.dll")]
public static extern IntPtr GetWindowDC(IntPtr hWnd);

[DllImport("coredll")]
public static extern int DeleteDC(IntPtr hdc);

[DllImportAttribute("coredll.dll")]
internal static extern IntPtr ReleaseDC(IntPtr hdc);

public const int SRCCOPY = 0x00CC0020;

[DllImport("coredll.dll")]
public static extern bool BitBlt(IntPtr hdcDest, 
    int nXDest, int nYDest, int nWidth, 
    int nHeight, IntPtr hdcSrc, int nXSrc, 
    int nYSrc, uint dwROP);

Windows Phone 7 using Silverlight

private void btnCaptureScreen_Click(object sender, RoutedEventArgs e)
{
    //Capture the screen and set it to the internal picture box
    WriteableBitmap bmp = new WriteableBitmap((int)this.ActualWidth, (int)this.ActualHeight);
    bmp.Render(this, null);
    bmp.Invalidate();
    this.image1.Source = bmp;
    
    //Set a new background
    ImageBrush brush = new ImageBrush();
    brush.ImageSource = new BitmapImage(new Uri(NextImage,UriKind.Relative));
    ContentGrid.Background = brush;
    
}

Essentially the apps do the same thing but it’s a lot easier to do it on one than the other.  Here are some quick highlights on the differences.

  1. Silverlight for Windows Phone 7 has 7 lines of code while the .NET Compact Framework version has 28 lines of code
  2. With Silverlight for Windows Phone 7 you don’t have to deal with PInvokes anymore.
  3. Windows Phone 7 codebase is a lot smaller and more maintainable.
  4. With silverlight for Windows Phone 7, controls automatically support transparencies which was a challenge on NETCF 3.5 (notice the white box on NETCF 3.5 screen, that’s a PictureBox control
  5. Currently on Windows Phone 7 there is no way to get the images from your device in the form of a file unless you upload to a web service or something similar

Give it a try for yourself and download the sample code here.

OpenNETCF Smart Device Framework 2.0 Beta 1

Smart Device Framework 2.0 Beta 1 from OpenNETCF has been released.  We have worked really hard to getting this ready and the redistributables for Beta 1 are now available.  The SDF2.0 documentation is also available online.


A lot of work was done throughout the whole SDF but some of the major changes was supporting the the new design time framework for controls for Visual Studio 2005.  Throughout the process we also decided to change some of the class names that ended with ‘Ex’ to ‘2’.  For example, OpenNETCF.Windows.Forms.ProgressBarEx is now OpenNETCF.Windows.Forms.ProgressBar2.


There are still some remaing minor issues with some controls and design time support for Visual Studio 2005.  See this post for some of those issues.


Also, check out the new Licensing Class available in the SDF 2.0.  It works the same as the full framework class so if you are looking to license your .NETCF application to your users this will help.


In a future post I will be writing some tips for creating and migrating controls for Visual Studio 2005.


WebBrowser Control Part II

As said in my previous post the SDF WebBrowser Control wraps HTMLView.dll which PocketIE uses.  On WindowsCE the SDF WebBrowser control will not browse to a http:// URLs but will work on a PocketPC.  .NET Compact Framework 2.0 has a standard WebBrowser control similar to the WebBrowser control in the Smart Device Framework. .NETCF 2.0 WebBrowser Control will work on both PocketPC and WindowsCE, but on WindowsCE you will need the Pro License and have the control as part of your OS image.


In my previous post I stated you could wrap IWebBrowser2.  Well, IWebBrowser2 is actually an interface so what you will have to wrap is shdocvw.dll.  IWebBrowser2 allows your application to create an instance of the WebBrowser control using ActiveX.  Of course this is all done in C++ using Embedded Visual C.


Sergey Bogdanov has actually done a lot of the work to get web browsing working in WindowsCE.  Download the sample project here


Here are some update links to get you started if you want some more technical information on the browser in CE. 


OpenNETCF SDF WebBrowser Control

The OpenNETCF SDF has a WebBrowser control under the OpenNETCF.Windows.Forms namespace.  There have been some “issues” with the WebBrowser control and using it on a WindowsCE device using .NETCF 1.0.  The WebBrowser control works on Pocket PC devices but does have limited functionality on Windows CE devices. 


First some background on the control.  The SDF WebBrowser control is a wrapper to the HTMLView.dll that come with PocketPCs.  This gives the functionality to browse URLs as long as you have connectivity.  For more technical information see here.  The SDF WebBrowser control wraps this functionality so it can be used in managed code and has design time support.  

On windows CE devices you cannot browse to external URLs but you can browse to files on the local device.  For example if you set the URL property on the WebBrowser control to file://[YOUR FILE] you should be able to see your file.  The reason for this is, WindowsCE uses HTMLView for Help files so it has limited functionality on a WindowsCE device. 


To have a full blown WebBrowser on windows CE there are a few things you have to do.  First, you have to pay for a Pro License which includes a full blown IE browser.  You may be able to get the Core license which has a scaled down version of IE but I’m not 100% sure.  Check here for more details or contact your distribution partner for more information. Second, you have to wrap IWebBrowser2 to be p/invoked from managed code and to display the unmanaged browser window within your unmanaged application.  This is not an easy task but is possible.


So basically, the OpenNETCF SDF WebBrowser control is fully functional and does not have any “bugs” or “issues” since we rely on the underlying OS.


Here are a few links to that may be of help if you attempt to wrap IWebBrowser2.  NOTE: There is an article on MSDN that goes through a C++ sample which is useful. I don’t have the link but will post if I find it.


WINCE
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceshdoc/html/ceconAddingInternetBrowsingFunctionalityToYourApplication.asp
http://msdn.microsoft.com/library/en-us/dnce30/html/iece30.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetcomp/html/HostingANativeWindowsControl.asp

Desktop – http://msdn.microsoft.com/workshop/browser/webbrowser/browser_control_node_entry.asp

TCPClient.ReceiveBufferSize

A couple of months ago I started creating a socket wrapper to make creating socket connections a little easier.  Yesterday, I started working on it again and came across a ‘bug’ when setting the ReceiveBufferSize.  I wanted to make the SendBufferSize and ReceiveBufferSize changeble by the user. Here is the code:


// Set these socket options
this.tcpClient.SendBufferSize = this.sendBufferSize;
this.tcpClient.ReceiveBufferSize = this.receiveBufferSize;


The error returned when setting ReceiveBufferSize was “An unknown, invalid, or unsupported option or level was specified in a getsockopt or setsockopt call”


Upon further investigation (and with help from Sandeep P.) by searching getsockopt and setsockopt from the error message I came accross this:







SO_RCVBUF int Specifies the total per-socket buffer space reserved for receives.
For Windows CE .NET 4.1 and later, the default buffer space is set to 8192 bytes. You can change the per-socket buffer space by calling setsockopt.

Note   This option is only supported for SOCK_DGRAM sockets.

So, basically Windows CE only supports setting the ReceiveBufferSize if you are using Datagrams (or UDP) and since I’m using TCP .NETCF throws the error.  It’s not really an bug, but something not supported by the underlying OS (Windows CE) which VS.NET2005 IDE let’s you see using IntelliSense. Don’t get me wrong IntelliSense has been greatly improved for Compact Framework (see here) and TCPClient.ReceiveBufferSize I’m sure is rarely used.


So if you’re doing some socket programming on a device be aware of this.  8K of buffer size should be big enough, but just be aware of this when using TCPClient.  


Note: On the desktop setting ReceiveBufferSize does not throw an exception.