Transferindo objetos shell com arrastar e soltar e a á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 de ou para a área de trabalho ou do Windows Explorer.

Embora os arquivos sejam o objeto Shell transferido com mais frequência, a transferência de dados do Shell pode envolver qualquer um dos diversos objetos encontrados no namespace 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 que não seja da Microsoft. Se você estiver implementando uma extensão de namespace, ela deverá ser capaz de se comportar corretamente como uma origem de soltar e um destino.

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

Como o arrastar e soltar funciona 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.
  • Copiar um arquivo para a Área de Transferência no Windows Explorer e colá-lo 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.

O Windows fornece duas maneiras padrão para 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 descarta o ícone em uma janela pertencente ao 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 fonte 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 transferências de dados de arrastar e soltar e área de transferência está 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 da á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 do objeto de dados.
  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 Manipulando operações de movimentação otimizada para obter um exemplo desse tipo de operação.

Transferências de dados de arrastar e soltar

Embora um pouco mais complexa 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 conforme ele passa 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 fonte de descarte deve fornecer funcionalidade além da necessária para transferências da Área de Transferência:

  • A fonte de soltar também deve criar um objeto que exponha uma interface IDropSource . O sistema usa IDropSource para se comunicar com a origem enquanto a operação está em andamento.
  • O objeto de dados 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 remoção também devem fornecer mais funcionalidade do que o necessário para lidar com transferências da Á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 arrastar e soltar:

  1. O destino chama RegisterDragDrop para dar ao sistema um ponteiro para sua interface IDropTarget e registrar uma janela como um destino de soltar.
  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 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::D ragEnter quando o cursor entra na janela de destino e IDropTarget::D ragOver à 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::D ragLeave. Quando qualquer um desses métodos retorna, o sistema chama a interface IDropSource para passar o valor retornado para a origem.
  4. Quando o usuário libera o botão do mouse para remover os dados, o sistema chama o método IDropTarget::D rop do destino. Entre os parâmetros do método está um ponteiro para a interface IDataObject do objeto de dados.
  5. O destino chama o método IDataObject::GetData do objeto de dados para extrair os dados.
  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 comentários à fonte sobre o resultado da transferência de dados.
  7. Quando o destino for concluído com o objeto de dados, ele retornará de IDropTarget::D rop. O sistema retorna a 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 origem 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 marcar esses valores para determinar se ele 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. Também há vários cenários de transferência de dados diferentes que seu aplicativo pode precisar lidar. Cada tipo de dados e cenário requer uma abordagem um pouco diferente para três etapas principais no procedimento:

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

O Objeto de Dados do 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.