The WP7 emulator still doesn’t support camera simulation in Windows Phone Developer Tools Beta. Several days ago, I found an interesting artcile in MSDN CODING4FUN talking about photo effect processing and camera capture on WP7. Then I have an idea – Why don’t we use normal webcams of PC to simulate the camera on WP7 emulator. Here is my trial.
In fact, it’s not difficult to get it work, we need a WebCam Gateway (WinForm application) which listens to specific HTTP port always return current captured image byte array as response when receive HTTP request. In WP7 side, we use WebClient to send HTTP request to the “WebCam Gateway” and get a stream with image data inside, the same way as what we do in CameraCaptureTask.Completed event.
WebCam Gateway WinForm Application
WebCam Gateway has only two primary goals: capture photo from webcam and works as a HTTP server! When it comes to webcam programming, WIA seems the easiest way. However, video content support is removed from WIA for Windows Vista. Microsoft recommends using the newer WPD API. I know nothing about webcam, so I picked an easier way, there is an “out-of-box” project, DxSnap, in DirectShow.NET library samples. I wrote a MicroHttpServer class using TcpListener to get request and return data, put it into DxSnap, and the WebCam Gateway is done.
Fig: Use IE to get photo from WebCam Gateway directly (click image to scale up)
Now, since we can use any browser to get current image of webcam, it’s easy to do the same thing in WP7. I wrote a CameraProxy class to encapsulate WebCam Gateway communication detail and try to make it’s behavior as similar as CameraCaptureTask as possible. So, there is a Show() method, a Completed(object sender, PhotoResult e) event that we can use the original CameraCaptureTask.Completed event handler to receive the image from WebCam Gateway. Unfortunately, PhotoResult.ChosenPhoto property is read-only, so I can’t use it to return image data. My solution is to declare a PhotoResultHacking class inheriting from PhotoResult and add a CamerPhotoStream property, and then we can extract the image data by detecting the argument type.
Here is the code of CameraProxy:
public class CameraProxy
private string gatewayUrl = null;
private IApplicationBar appBar = null;
private Border mask = new Border()
Background = new SolidColorBrush(Colors.White),
Opacity = 0.7,
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
Visibility = Visibility.Collapsed
//Constructor, url for WebCam Gateway, page for UI blocking
public CameraProxy(string url, PhoneApplicationPage page)
gatewayUrl = url;
if (page != null)
appBar = page.ApplicationBar;
//Try to get LayoutRoot element
Panel pnl =
VisualTreeHelper.GetChild(page, 0) as Panel;
//If the LayoutRoot is a container
if (pnl != null) //Add a mask element
mask = null;
//Completed event compatible with CameraCaptureTask
public event Action<object, PhotoResult> Completed;
public void Show()
WebClient wc = new WebClient();
wc.OpenReadCompleted += (sender, e) =>
//e.Result is the stream that contains image we need
PhotoResultHacking pr = new PhotoResultHacking(
if (Completed != null)
//If any exception, return TaskResult.Cancel
PhotoResult epr = new PhotoResult(TaskResult.Cancel);
if (Completed != null)
//Remove the blocking mask
if (mask != null)
mask.Visibility = Visibility.Collapsed;
//Show the ApplicationBar
if (appBar != null)
appBar.IsVisible = true;
//Add a mask to block the UI
if (mask != null)
mask.Visibility = Visibility.Visible;
//Hide ApplicationBar to block the UI
if (appBar != null)
appBar.IsVisible = false;
//A **compatible** PhotoResult providing writable property
public class PhotoResultHacking : PhotoResult
public Stream CameraPhotoStream;
public PhotoResultHacking(TaskResult result, Stream stream) :
CameraPhotoStream = stream;
How to Use
I modified PicFx project to show how to use CameraProxy.
First, we create CameraProxy object in Initialize() and useCompleted event handler of CameraCaptureTask.
private void Initialize()
// Init tasks
cameraCaptureTask = new CameraCaptureTask();
cameraCaptureTask.Completed += PhotoProviderTaskCompleted;
//Create CameraProxy object and shared the same event handler
//PS: 192.168.1.136 is the local IP address of host
cameraProxy = new Darkthread.CameraProxy(
cameraProxy.Completed += PhotoProviderTaskCompleted;
In orginal project, the Camera button is disabled in emulator mode, now let’s turn it on.
if (btn != null)
//btn.IsEnabled = Microsoft.Devices.Environment.DeviceType
// != DeviceType.Emulator;
btn.IsEnabled = true;
When camera button is clicked, either cameraProxy.Show() or cameraCaptureTaskShow() is called depending on EmulatorMode flag. Event handler PhotoProviderTaskCompleted is shared among cameraProxy, cameraCaptureTask, and photoChooserTask, so inside the event we have to detect if the result is returned by cameraProxy to cast the result parameter to PhotoResultHacking class, so we get image data correctly from extra CameraPhotoStream property.
Final part is ugly but seems unavoidable. CameraCaptureTask and PhotoChooser are handled by operation system, they will terminate the application and launch it again after task, but I don’t think it’s possible to simulate the same behavior by our code. In original design, some job after image captured is arranged in Initialize() and LayoutUpdated(), So only thing I can do is to move these necessary images preparing logic to Completed event.
//**CameraProxy** Add a flag to identify if it's in emulator mode
private bool EmulatorMode
private void ApplicationBarIconCameraButton_Click(object sender, EventArgs e)
//Trigger CameraCaptureTask or CameraProxy depends on EmulatorMode flag
private void PhotoProviderTaskCompleted(object sender, PhotoResult e)
// Load the photo from the task result
if (e != null && e.TaskResult == TaskResult.OK)
var bmpi = new BitmapImage();
//**CameraProxy** add branch code for CameraProxy
bool extCamera = (EmulatorMode &&
e is Darkthread.PhotoResultHacking);
original = new WriteableBitmap(bmpi);
//Real CameraCaptureTask will terminate the application
//and cause Loaded event, but CameraProxy won't,
//so we have to add the logic after camera capture here.
//Ugly, but seems no better way
That’s all! Now we can use the WP7 emulator to **take a shot**, have fun!
You can download the WebCam Gateway source code with CameraProxy.cs, modified MainPage.xaml.cs from here.
Any feedback is welcome.