Transferência de objetos do Shell por arrastar e soltar e pela Área de Transferência

Muitos aplicativos permitem que os usuários transfiram dados para outro aplicativo arrastando e soltando os dados com o mouse ou usando a Área de Transferência. Entre os muitos tipos de dados que podem ser transferidos estão objetos Shell, como arquivos ou pastas. A transferência de dados do Shell pode ocorrer entre dois aplicativos, mas os usuários também podem transferir dados do Shell para ou da área de trabalho ou do Windows Explorer.

Embora os arquivos sejam o objeto Shell mais comumente transferido, a transferência de dados do Shell pode envolver qualquer um dos diversos objetos encontrados no namespace do Shell. Por exemplo, seu aplicativo pode precisar transferir um arquivo para uma pasta virtual, como a Lixeira, ou aceitar um objeto de uma extensão de namespace não Microsoft. Se você estiver implementando uma extensão de namespace, ela deverá ser capaz de se comportar corretamente como uma origem e destino de arrastar e soltar.

Este documento discute como os aplicativos podem implementar transferências de dados de arrastar e soltar e da Área de Transferência com objetos Shell.

Como funciona o Drag-and-Drop com objetos Shell

Os aplicativos geralmente precisam fornecer aos usuários uma maneira de transferir dados do Shell. Alguns exemplos são:

  • Arrastando um arquivo do Windows Explorer ou da área de trabalho e soltando-o em um aplicativo.
  • Copiando um arquivo para a Área de Transferência no Windows Explorer e colando-o em um aplicativo.
  • Arrastando um arquivo de um aplicativo para a Lixeira.

Para obter uma discussão detalhada sobre como lidar com esses e outros cenários, consulte Manipulando cenários de transferência de dados do Shell. Este documento se concentra nos princípios gerais por trás da transferência de dados do Shell.

Windows fornece duas maneiras padrão para os aplicativos transferirem dados do Shell:

  • Um usuário corta ou copia dados do Shell, como um ou mais arquivos, para a Área de Transferência. O outro aplicativo recupera os dados da Área de Transferência.
  • Um usuário arrasta um ícone que representa os dados do aplicativo de origem e solta o ícone em uma janela de propriedade do destino.

Em ambos os casos, os dados transferidos estão contidos em um objeto de dados. Objetos de dados são objetos COM (Component Object Model) que expõem a interface IDataObject . Esquematicamente, há três etapas essenciais que todas as transferências de dados do Shell devem seguir:

  1. A origem cria um objeto de dados que representa os dados que devem ser transferidos.
  2. O destino recebe um ponteiro para a interface IDataObject do objeto de dados.
  3. O destino chama a interface IDataObject para extrair os dados dele.

A diferença entre a Área de Transferência e as transferências de dados por arrastar e soltar reside principalmente em como o ponteiro IDataObject é transferido da origem para o destino.

Transferências de dados da área de transferência

A Área de Transferência é a maneira mais simples de transferir dados do Shell. O procedimento básico é semelhante às transferências de dados padrão da Área de Transferência. No entanto, como você está transferindo um ponteiro para um objeto de dados, não os dados em si, você deve usar a API de área de transferência OLE em vez da API de área de transferência padrão. O procedimento a seguir descreve como usar a API da área de transferência OLE para transferir dados do Shell com a Área de Transferência:

  1. A fonte de dados cria um objeto de dados para conter os dados.
  2. A fonte de dados chama OleSetClipboard, que coloca um ponteiro para a interface IDataObject do objeto de dados na área de transferência.
  3. O destino chama OleGetClipboard para recuperar o ponteiro para a interface IDataObject.
  4. O destino extrai os dados chamando o método IDataObject::GetData .
  5. Com algumas transferências de dados do Shell, o destino também pode precisar chamar o método IDataObject::SetData do objeto de dados para fornecer comentários ao objeto de dados sobre o resultado da transferência de dados. Consulte Como lidar com operações de movimentação otimizadas para obter um exemplo desse tipo de operação.

Transferência de dados por arrastar e soltar

Embora seja um pouco mais complexo de implementar, a transferência de dados de arrastar e soltar tem algumas vantagens significativas sobre a Área de Transferência:

  • As transferências de arrastar e soltar podem ser feitas com um movimento simples do mouse, tornando a operação mais flexível e intuitiva de usar do que a Área de Transferência.
  • Arrastar e soltar fornece ao usuário uma representação visual da operação. O usuário pode seguir o ícone à medida que ele se move da origem para o destino.
  • Arrastar e soltar notifica o destino quando os dados estão disponíveis.

As operações de arrastar e soltar também usam objetos de dados para transferir dados. No entanto, a origem de arrastar e soltar deve fornecer funcionalidade além da necessária para transferências da área de transferência:

  • A origem de arraste também deve criar um objeto que exponha uma interface IDropSource. O sistema usa o IDropSource para se comunicar com o objeto de origem enquanto a operação está em andamento.
  • O objeto de dados de arrastar e soltar é responsável por acompanhar a movimentação do cursor e exibir um ícone para representar o objeto de dados.

Os destinos de arrasto também devem oferecer mais funcionalidades do que as necessárias para lidar com transferências pela Área de Transferência.

  • O destino de soltar deve expor uma interface IDropTarget . Quando o cursor está sobre uma janela de destino, o sistema usa IDropTarget para fornecer ao destino informações como a posição do cursor e notificá-lo quando os dados são descartados.
  • O destino de soltar deve se registrar no sistema chamando RegisterDragDrop. Essa função fornece ao sistema o identificador para uma janela de destino e um ponteiro para a interface IDropTarget do aplicativo de destino.

Observação

Para operações de arrastar e soltar, seu aplicativo deve inicializar COM com OleInitialize, não CoInitialize.

 

O procedimento a seguir descreve as etapas essenciais que normalmente são usadas para transferir dados do Shell com o recurso de arrastar e soltar:

  1. O destino chama RegisterDragDrop para fornecer ao sistema um ponteiro para sua interface IDropTarget e registrar uma janela como um destino de arrasto.
  2. Quando o usuário inicia uma operação de arrastar e soltar, a origem cria um objeto de dados e inicia um loop de arrastar e soltar chamando DoDragDrop.
  3. Quando o cursor está sobre a janela de destino, o sistema notifica o destino chamando um dos métodos IDropTarget do destino. O sistema chama IDropTarget::DragEnter quando o cursor entra na janela de destino e IDropTarget::DragOver à medida que o cursor passa pela janela de destino. Ambos os métodos fornecem o destino de soltar com a posição atual do cursor e o estado das teclas modificadoras de teclado, como CTRL ou ALT. Quando o cursor sai da janela de destino, o sistema notifica o destino chamando IDropTarget::DragLeave. Quando qualquer um desses métodos retorna, o sistema chama a interface IDropSource a fim de passar o valor retornado para a origem.
  4. Quando o usuário libera o botão do mouse para soltar os dados, o sistema chama o método IDropTarget::Drop do destino. Entre os parâmetros do método está um ponteiro para a interface IDataObject do objeto de dados.
  5. O aplicativo de destino chama o método IDataObject::GetData do objeto de dados para extrair-los.
  6. Com algumas transferências de dados do Shell, o destino também pode precisar chamar o método IDataObject::SetData do objeto de dados para fornecer feedback à origem sobre o resultado da transferência de dados.
  7. Quando o destino termina de usar o objeto de dados, ele retorna de IDropTarget::Drop. O sistema retorna à chamada DoDragDrop da origem para notificar a origem de que a transferência de dados foi concluída.
  8. Dependendo do cenário de transferência de dados específico, a fonte pode precisar tomar medidas adicionais com base no valor retornado por DoDragDrop e nos valores que são passados para o objeto de dados pelo destino. Por exemplo, quando um arquivo é movido, a origem deve verificar esses valores para determinar se ela deve excluir o arquivo original.
  9. A origem libera o objeto de dados.

Embora os procedimentos descritos acima forneçam um bom modelo geral para transferência de dados do Shell, há muitos tipos diferentes de dados que podem ser contidos em um objeto de dados shell. Há também uma série de cenários diferentes de transferência de dados com os quais o aplicativo precise lidar. Cada tipo de dados e cenário requer uma abordagem um pouco diferente para três etapas principais no procedimento:

  • Como uma origem constrói um objeto de dados para conter os dados do Shell.
  • Como um alvo extrai dados do Shell de um objeto de dados.
  • Como a origem conclui a operação da transferência de dados.

O Objeto de Dados Shell fornece uma discussão geral sobre como uma fonte constrói um objeto de dados Shell e como esse objeto de dados pode ser tratado pelo destino. Lidar com cenários de transferência de dados do Shell discute detalhadamente como lidar com vários cenários comuns de transferência de dados do Shell.