How do I show the sharing pane from a Win32 desktop application?


A customer wanted to show the sharing pane from their Win32 desktop application. In a UWP application, this would be done by calling Windows.Application­Model.Data­Transfer.Data­Transfer­Manager.Show­Sharing­UI(). Let's do it in a Win32 desktop app by following the basic rules for projection: Static methods are represented as methods on a "Statics" interface on the activation factory.

Start with the scratch program and make these changes. (Remember, Little Programs do little to no error checking.)

#include <wrl/client.h>
#include <wrl/wrappers/corewrappers.h>
#include <windows.applicationmodel.datatransfer.h>
#include <tchar.h> // Huh? Why are you still using ANSI?
#include <roapi.h>

namespace WRL = Microsoft::WRL;
namespace dt = ABI::Windows::ApplicationModel::DataTransfer;

using Microsoft::WRL::Wrappers::HStringReference;

void OnChar(HWND hwnd, TCHAR ch, int cRepeat)
{
  switch (ch) {
  case TEXT(' '):
    {
      WRL::ComPtr<dt::IDataTransferManagerStatics> dtmStatics;
      RoGetActivationFactory(HStringReference(
        RuntimeClass_Windows_ApplicationModel_DataTransfer_DataTransferManager)
                             .Get(), IID_PPV_ARGS(&dtmStatics));
      dtmStatics->ShowShareUI();
    }
    break;
  }
}

HANDLE_MSG(hwnd, WM_CHAR, OnChar);

Fire up this program, hit the space bar, and… nothing happens.

Okay, so maybe we need to do a tiny bit of error checking after all. The call to Show­Share­UI fails with E_NOT_SET. The reason is that the Show­Share­UI method has an implicit dependency on the current thread's Core­Window, because it needs to know which window is being shared. But since we are a Win32 desktop program, we don't have a Core­Window.

Oh no, what do we do?

Enter the interop pattern.

To accommodate Win32 desktop programs, there is a parallel universe of HWND-based methods. In places where WinRT depends on the current thread's Core­Window, this alternative universe offers a similarly-named method, but with the For­Window suffix, indicating that it operates on classic Win32 HWNDs rather than fancy-pants Core­Windows.

One component of this parallel universe of -For­Window methods consists of interfaces that end in the name Interop. In our case, it's IData­Transfer­Manager­Interop. This interface is available on the activation factory, the same as the IData­Transfer­Manager­Statics interface. The general pattern is as follows:

XxxStatics XxxInterop
Get­For­Current­View Get­For­Window
Do­Something (implied "for current view") Do­Something­For­Window

In our case, we have a Show­Sharing­UI() method on the Statics interface, so the corresponding interop method is called Show­Sharing­For­WIndow().

#include <shlobj.h> // IDataTransferManagerInterop

void OnChar(HWND hwnd, TCHAR ch, int cRepeat)
{
  switch (ch) {
  case TEXT(' '):
    {
      WRL::ComPtr<dt::IDataTransferManagerInterop> dtmInterop;
      RoGetActivationFactory(HStringReference(
        RuntimeClass_Windows_ApplicationModel_DataTransfer_DataTransferManager)
                             .Get(), IID_PPV_ARGS(&dtmInterop));
      dtmInterop->ShowShareUIForWindow(hwnd);
    }
    break;
  }
}

Okay, so now we show the share pane, but the pane just offers to share a screen shot. How can we get the pane to offer custom data provided by the program? We'll look at that next time.

Bonus chatter: One of my colleagues noted that "data transfer manager" is a poor name for the class, seeing as transferring data is what computers do most of the time anyway.

Comments (12)

  1. Entegy says:

    Ooh, this is great to know it’s possible to get the sharing pane in a Win32 app.

  2. pc says:

    Probably just a typo, but the text talks about “Show­Sharing­UI” and “ShowSharing­For­WIndow”, but code has “ShowShareUI” and “ShowShareUIForWindow”. I haven’t yet had the pleasure of playing with UWP yet, so perhaps I missed something.

  3. skSdnW says:

    I found out the hard way that ShowShareUIForWindow only works on Windows 10+, on Windows 8 it returns S_OK but does nothing when called from a normal desktop app. I’m assuming it only works for the Metro browser on Windows 8?

  4. Lawrence says:

    Hmm, I admit I have no idea what the “Sharing Pane” is. Google/Bing search for “Sharing Pane” and “Sharing UI” shows mostly MacOS stuff and some 3rd party apps… nothing that looks like a Windows OS feature.

    I’m on Windows 10, how can I access this as a user?

    1. skSdnW says:

      In Windows 8 it was on the Charms bar, in Windows 10 it is just a icon inside the app. It used to look like “holding hands in a circle” but it is now supposed to look more like iOS: https://medium.com/microsoft-design/the-iconography-of-sharing-183a1ad9c6f1#

      1. Medinoc says:

        So *that*’s what it was supposed to look like! I couldn’t fathom a signification behind that sharing icon (which I never use anyway).

        1. skSdnW says:

          I don’t know if that is what it really is supposed to be but it is similar to the Ubuntu logo where it is called the “Circle of Friends”[1]

          1: http://design.ubuntu.com/brand/ubuntu-logo

          1. MarcK4096 says:

            I see it in the Ubuntu one. In the Microsoft one, I see an atom, possibly warning of nuclear danger.

  5. henke37 says:

    I think you forgot to roll the die to decide on the smart com pointer class to use.

    1. Nick says:

      This assumes you have a choice of smart pointer. In theory you do (I’m assuming the WRL deallocator is projected somewhere, I live in managed memory land so I don’t worry about these things), but why use any one other than the one that comes with the library you’re interacting with?

      1. MarcK4096 says:

        I love managed memory land. :)

  6. JAHA says:

    Preemptive Dad joke: “No more sharing pain with the sharing pane”

Skip to main content