Operações de área de transferência
Uma janela deve usar a área de transferência ao cortar, copiar ou colar dados. Uma janela coloca dados na área de transferência para operações de recortar e copiar e recupera dados da área de transferência para operações de colagem. As seções a seguir descrevem essas operações e problemas relacionados.
Para colocar dados ou recuperar dados da área de transferência, uma janela deve primeiro abrir a área de transferência usando a função OpenClipboard. Apenas uma janela pode abrir a área de transferência de cada vez. Para descobrir qual janela tem a área de transferência aberta, chame a função GetOpenClipboardWindow. Quando terminar, a janela deverá fechar a área de transferência chamando a função CloseClipboard.
Os tópicos a seguir são discutidos nesta seção.
- operações de recortar e copiar
- operações de colagem
- de Propriedade da Área de Transferência
- de renderização atrasada
- memória e a área de transferência
Operações de recortar e copiar
Para colocar informações na área de transferência, uma janela primeiro limpa qualquer conteúdo da área de transferência anterior usando a função EmptyClipboard. Essa função envia a mensagem WM_DESTROYCLIPBOARD ao proprietário da área de transferência anterior, libera recursos associados aos dados na área de transferência e atribui a propriedade da área de transferência à janela que tem a área de transferência aberta. Para descobrir qual janela possui a área de transferência, chame a função GetClipboardOwner.
Depois de esvaziar a área de transferência, a janela coloca os dados na área de transferência no maior número possível de formatos de área de transferência, ordenados do formato de área de transferência mais descritivo para o menos descritivo. Para cada formato, a janela chama a função SetClipboardData, especificando o identificador de formato e um identificador de memória global. O identificador de memória pode ser NULL, indicando que a janela renderiza os dados na solicitação. Para obter mais informações, consulte de renderização atrasada.
Operações de colagem
Para recuperar informações de colagem da área de transferência, uma janela primeiro determina o formato da área de transferência a ser recuperada. Normalmente, uma janela enumera os formatos de área de transferência disponíveis usando a função EnumClipboardFormats e usa o primeiro formato que reconhece. Esse método seleciona o melhor formato disponível de acordo com o conjunto de prioridades quando os dados foram colocados na área de transferência.
Como alternativa, uma janela pode usar a funçãoGetPriorityClipboardFormat. Essa função identifica o melhor formato de área de transferência disponível de acordo com uma prioridade especificada. Uma janela que reconhece apenas um formato de área de transferência pode simplesmente determinar se esse formato está disponível usando a função IsClipboardFormatAvailable.
Depois de determinar o formato da área de transferência a ser usado, uma janela chama a função GetClipboardData. Essa função retorna o identificador para um objeto de memória global que contém dados no formato especificado. Uma janela pode bloquear brevemente o objeto de memória para examinar ou copiar os dados. No entanto, uma janela não deve liberar o objeto ou deixá-lo bloqueado por um longo período de tempo.
Propriedade da área de transferência
O proprietário da área de transferência é a janela associada às informações na área de transferência. Uma janela se torna o proprietário da área de transferência quando coloca dados na área de transferência, especificamente, quando chama a função EmptyClipboard. A janela permanece o proprietário da área de transferência até que seja fechada ou outra janela esvazie a área de transferência.
Quando a área de transferência é esvaziada, o proprietário da área de transferência recebe uma mensagem WM_DESTROYCLIPBOARD. Veja a seguir alguns motivos pelos quais uma janela pode processar esta mensagem:
- A janela atrasou a renderização de um ou mais formatos de área de transferência. Em resposta à mensagem WM_DESTROYCLIPBOARD, a janela pode liberar recursos alocados para renderizar dados sob solicitação. Para obter mais informações sobre a renderização de dados, consulte de Renderização Atrasada.
- A janela colocou dados na área de transferência em um formato de área de transferência privada. Os dados para formatos de área de transferência privada não são liberados pelo sistema quando a área de transferência é esvaziada. Portanto, o proprietário da área de transferência deve liberar os dados ao receber a mensagem de WM_DESTROYCLIPBOARD. Para obter mais informações sobre formatos de área de transferência privada, consulte formatos de área de transferência.
- A janela colocou dados na área de transferência usando o formato da área de transferência CF_OWNERDISPLAY. Em resposta à mensagem WM_DESTROYCLIPBOARD, a janela pode liberar recursos usados para exibir informações na janela do visualizador da área de transferência. Para obter mais informações sobre esse formato alternativo, consulte Formato de Exibição do Proprietário.
Renderização atrasada
Ao colocar um formato de área de transferência na área de transferência, uma janela pode atrasar a renderização dos dados nesse formato até que os dados sejam necessários. Para fazer isso, um aplicativo pode especificar NULL para o parâmetro hData da funçãoSetClipboardData. Isso será útil se o aplicativo der suporte a vários formatos de área de transferência, alguns ou todos os quais são demorados para renderizar. Ao passar um identificador de NULL, uma janela renderiza formatos de área de transferência complexos somente quando e se forem necessários.
Se uma janela atrasar a renderização de um formato de área de transferência, ela deverá estar preparada para renderizar o formato mediante solicitação, desde que seja o proprietário da área de transferência. O sistema envia ao proprietário da área de transferência uma mensagem de WM_RENDERFORMAT quando uma solicitação é recebida para um formato específico que não foi renderizado. Ao receber essa mensagem, a janela deve chamar a função SetClipboardData para colocar um identificador de memória global na área de transferência no formato solicitado.
Um aplicativo não deve abrir a área de transferência antes de chamar SetClipboardData em resposta à mensagem WM_RENDERFORMAT. Não é necessário abrir a área de transferência e qualquer tentativa de fazer isso falhará porque a área de transferência está sendo aberta pelo aplicativo que solicitou que o formato fosse renderizado.
Se o proprietário da área de transferência estiver prestes a ser destruído e tiver atrasado a renderização de alguns ou todos os formatos de área de transferência, ele receberá a mensagem WM_RENDERALLFORMATS. Ao receber essa mensagem, a janela deve abrir a área de transferência, verificar se ela ainda é o proprietário da área de transferência com a função GetClipboardOwner e, em seguida, colocar identificadores de memória válidos na área de transferência para todos os formatos de área de transferência que ele fornece. Isso garante que esses formatos permaneçam disponíveis depois que o proprietário da área de transferência for destruído.
Ao contrário do WM_RENDERFORMAT, um aplicativo que responde a WM_RENDERALLFORMATS deve abrir a área de transferência antes de chamar SetClipboardData para colocar todos os identificadores de memória globais na área de transferência.
Todos os formatos de área de transferência que não são renderizados em resposta ao WM_RENDERALLFORMATS mensagem deixam de estar disponíveis para outros aplicativos e não são mais enumerados pelas funções da área de transferência.
Diretrizes de renderização atrasadas
A renderização atrasada é um recurso de desempenho, permitindo que um aplicativo evite realizar trabalhos para renderizar dados da área de transferência em um formato que talvez nunca seja solicitado. No entanto, o uso de renderização atrasada envolve as seguintes compensações que devem ser levadas em consideração:
- O uso de renderização atrasada adiciona alguma complexidade ao aplicativo, exigindo que ele manipule duas mensagens de janela de renderização, conforme descrito acima.
- Usar a renderização atrasada significa que o aplicativo perde a opção de manter a interface do usuário responsiva se a renderização dos dados levar tempo suficiente para ser perceptível para o usuário. Com a renderização atrasada, se os dados forem eventualmente necessários, a janela deverá renderizar os dados durante o processamento de uma mensagem de janela de renderização, conforme descrito acima. Como resultado, se os dados forem muito demorados para serem renderizados, o aplicativo poderá ficar visivelmente sem resposta (travado) durante a renderização, pois nenhuma outra mensagem de janela pode ser processada enquanto a mensagem da janela de renderização está sendo processada. Um aplicativo que não usa a renderização atrasada pode optar por renderizar dados em um thread em segundo plano para manter a resposta da interface do usuário durante a renderização, talvez fornecendo opções de progresso ou cancelamento, que não estão disponíveis ao usar a renderização atrasada.
- O uso da renderização atrasada adicionará uma pequena quantidade de sobrecarga se os dados forem eventualmente necessários. Ao usar a renderização de atraso, uma janela inicialmente chama a função SetClipboardData com um identificador NULL e, se os dados forem necessários posteriormente, a janela deverá responder a uma mensagem de janela e chamar a função SetClipboardData uma segunda vez com um identificador para os dados renderizados, conforme descrito acima. Como resultado, se os dados forem eventualmente necessários, usar a renderização atrasada adicionará o custo de processar uma mensagem de janela e chamar a função SetClipboardData uma segunda vez. Esse custo é pequeno, mas não zero. Se um aplicativo oferecer suporte apenas a um único formato de área de transferência e se os dados forem sempre solicitados eventualmente, usar a renderização atrasada apenas adicionará essa pequena quantidade de sobrecarga (o custo varia de acordo com o hardware; uma estimativa está entre 10 e 100 microssegundos). No entanto, se os dados forem pequenos, a sobrecarga de usar a renderização atrasada poderá exceder o custo para renderizar os dados, o que pode derrotar a finalidade de usar a renderização atrasada para melhorar o desempenho. (Em testes, para dados que já estão em sua forma final, a sobrecarga de usar a renderização atrasada excedeu consistentemente o custo para copiar os dados para a área de transferência se os dados tiverem 100 KiB ou menos. Esse teste não inclui o custo para renderizar dados, apenas para copiá-los depois que eles são renderizados.)
- A renderização atrasada será uma vantagem de desempenho líquido se economizar mais tempo do que adiciona em sobrecarga. Para determinar a sobrecarga da renderização atrasada, a medição é melhor, mas de 10 a 100 microssegundos é uma estimativa. Para calcular a economia de uso da renderização atrasada para cada formato de área de transferência, meça o custo para renderizar os dados nesse formato e determine com que frequência esse formato é eventualmente solicitado (com base nas mensagens de janela descritas acima). Multiplique o custo de renderização dos dados pela porcentagem de tempo em que os dados não são eventualmente solicitados (antes que a área de transferência seja esvaziada ou seu conteúdo seja alterado) para determinar a economia de renderização atrasada para cada formato de área de transferência. A renderização atrasada será uma vantagem de desempenho líquido se a economia exceder o custo de sobrecarga.
- Como uma diretriz concreta, para aplicativos que dão suporte apenas a um único formato de área de transferência, como texto, em que os dados não são significativamente caros de renderizar, considere colocar os dados diretamente na área de transferência se o tamanho dos dados for 4 KiB ou menos.
Memória e área de transferência
Um objeto de memória que deve ser colocado na área de transferência deve ser alocado usando a função GlobalAlloc com o sinalizador GMEM_MOVEABLE.
Depois que um objeto de memória é colocado na área de transferência, a propriedade desse identificador de memória é transferida para o sistema. Quando a área de transferência é esvaziada e o objeto de memória tem um dos seguintes formatos de área de transferência, o sistema libera o objeto de memória chamando a função especificada:
Função para objeto livre | Formato de área de transferência |
---|---|
DeleteMetaFile |
CF_DSPENHMETAFILE CF_DSPMETAFILEPICT CF_ENHMETAFILE CF_METAFILEPICT |
DeleteObject |
CF_BITMAP CF_DSPBITMAP CF_PALETTE |
GlobalFree |
CF_DIB CF_DIBV5 CF_DSPTEXT CF_OEMTEXT CF_TEXT CF_UNICODETEXT |
nenhum |
CF_OWNERDISPLAY Quando a área de transferência é esvaziada de um objeto CF_OWNERDISPLAY, o próprio aplicativo deve liberar o objeto de memória. |