March 15th, 2017

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.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

0 comments

Discussion are closed.