The share contract is the API that drives the share charm (on Windows 8) and share button on Windows. This feature has been around since 2012. Thousands of app in the Windows and Windows Phone app stores share content using the share contract. That’s because the share APIs are a great way to share content with social networks, email, text messaging and any other communication apps a user might have installed on their device. If you’re not familiar with the API, this MSDN article is a good starting point as is my Build talk from last year.
However, one thing that has always bothered me about share is that all the existing Win32, WinForms and Windows Presentation Foundation (WPF) apps can’t share content using these APIs. Well, we set out to remedy that situation last year as we started building out Windows 10. As we were building out the feature, we brought in partners early on who could help us validate our code. The File Explorer team kindly signed up to share files with Modern apps and that gave us a lot of early test data and helped us iron out bugs in the feature. If you’d like to try out the feature on Windows 10, just go into the file explorer and select a file, open the Share ribbon on top and click the Share button.
|Important Note: When sharing from a Win32 app, two requirements apply:
Now that we’re coming up on Build I wanted to talk about this feature and walk through how a Win32, WinForms or WPF app can share content on Windows 10. If you’re the kind of person who wants to jump straight into code, well, it all lives here: https://github.com/arunjeetsingh/Build2015/tree/master/Win32ShareSourceSamples. Feel free to clone, log bugs and submit pull requests if you have fixes for me. From this point on, I’m going to assume you’re looking at the code and can follow along. Lets start by taking a look at the WPF project called WpfShareSource. This project shows how a WPF app can share text, URI or a file using the share API. Of course, you can also share any of the other formats if you want to but these happen to be the most common ones so they’re a good starting point.
The WpfShareSource.csproj file contains a set of references that you might not find in a typical WPF project. To be precise, there are references to three new things:
- System.Runtime.dll gives us access to some runtime related features used by the Windows 10 (and 8) API surface. This includes things like iterators and async operations.
- System.Runtime.WindowsRuntime gives us access to some nice .NET friendly wrappers for APIs like RoGetActivationFactory.
- The Windows.winmd reference gives us access to the complete Windows 10 API surface
Note that you might have to update the paths depending upon how you’re set up. It’s something I’m hoping to remedy with a future commit.
Figure 2: The IDataTransferManagerInterOp interface
Okay, so now we have a WPF project that can consume Windows 10 APIs. Nothing new there, you could do this with Windows 8 as well. The really interesting bits live in a file called DataTransferManagerHelper.cs. The first thing worth noting is the IDataTransferManagerInterOp interface defined at the bottom of the file. We need to bring this interface in because it is a COM interface that isn’t already available in WPF or WinRT. This interface really is the thing that drives a Win32 app’s interaction with the share infrastructure. IDataTransferManagerInterOp has two methods:
- GetForWindow – Those method lets a Win32 app get a DataTransferManager attached to a given window handle (usually the app’s own main window). Note that this is the same DataTransferManager that Modern apps use. But while Modern apps use the GetForCurrentView static method to get an instance of DataTransferManager, Win32 apps must use IDataTransferManager.GetForWindow.
- ShowShareUIForWindow – This is the method a Win32 app must call to pop open the share picker. All it needs is a window handle. As with Modern apps, the request to retrieve data comes in via the OnDataRequested event hanging off of the DataTransferManager class.
Figure 3: The DataTransferManagerHelper class
The DataTransferHelper class is a nice wrapper around IDataTransferManagerInterOp. The constructor of this class accepts a window handle. It gets an activation factory for DataTransferManager and casts it to an IDataTransferManagerInterop. Then we use the IDataTransferInterOp instance to get a hold of a DataTransferManager instance using the GetForWindow method. We hold on to the DataTransferManager instance as a property on the DataTransferManagerHelper. We also hold on to the instance of IDataTransferInterOp as a member variable. Finally, DataTransferManagerHelper.ShowShareUI simply calls ShowShareUIForWindow on the IDataTransferManagerInterOp instance it’s holding. Okay, now that we have all the pieces in place, lets take a quick look at MainPage.xaml.cs where all the action happens. On MainPage, we’ve got a button each to share a piece of text, a weblink and a file. The click handlers of these buttons simply ensure that a DataTransferManager is set up, put the app into the right sharing mode (text, weblink or file) and kick off share by calling the DataTransferManager.ShowShareUI method.
Figure 4: MainPage.xaml.cs -> EnsureDataTransferManager
The EnsureDataTransferManager method creates a new DataTransferHelper if one doesn’t already exist and then sets up a handler for the DataTransferManager.DataRequested event. The DataRequested handler is the code that the share picker calls once it is ready to pull the data it needs for sharing. That’s it! That’s how a WPF app can share content with Modern share targets on a Windows 10 device. The solution also has projects showing how a WinForms .NET app can share content as well as a simple Win32 app that shares text. Happy hacking!