Operações da Á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 corte e cópia 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 ter a área de transferência aberta de cada vez. Para descobrir qual janela tem a área de transferência aberta, chame o função GetOpenClipboardWindow. Quando terminar, a janela deve fechar a área de transferência chamando a funçãoCloseClipboard.
Os tópicos a seguir são discutidos nesta seção.
- Operações de corte e cópia
- de 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 corte e cópia
Para colocar informações na área de transferência, uma janela primeiro limpa qualquer conteúdo anterior da área de transferência usando a função EmptyClipboard. Esta função envia a mensagem WM_DESTROYCLIPBOARD para o proprietário anterior da área de transferência, 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çãoGetClipboardOwner.
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 mais descritivo da área de transferência para o menos descritivo. Para cada formato, a janela chama o 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 processa os dados mediante solicitação. Para obter mais informações, consulte 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 recuperado. 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. Este método seleciona o melhor formato disponível de acordo com a prioridade definida quando os dados foram colocados na área de transferência.
Como alternativa, uma janela pode usar a funçãoGetPriorityClipboardFormat. Esta 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 da área de transferência pode simplesmente determinar se esse formato está disponível usando a funçãoIsClipboardFormatAvailable.
Depois de determinar o formato da área de transferência a ser usado, uma janela chama a funçãoGetClipboardData. Esta 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 libertar 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 torna-se o proprietário da área de transferência quando coloca dados na área de transferência, especificamente, quando chama a funçãoEmptyClipboard. A janela permanece o proprietário da área de transferência até ser fechada ou outra janela esvaziar 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. A seguir estão algumas razões pelas quais uma janela pode processar essa mensagem:
- A janela atrasou a renderização de um ou mais formatos da área de transferência. Em resposta à mensagem WM_DESTROYCLIPBOARD, a janela pode liberar recursos alocados para renderizar dados mediante solicitação. Para obter mais informações sobre a renderização de dados, consulte de renderização atrasada .
- A janela colocou os dados na área de transferência em um formato de área de transferência privada. Os dados para formatos privados da área de transferência 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 WM_DESTROYCLIPBOARD. Para obter mais informações sobre formatos de área de transferência privados, consulte Formatos da área de transferência.
- A janela colocou dados na área de transferência usando o formato CF_OWNERDISPLAY área de transferência. 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 do. Isso é útil se o aplicativo suportar 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 processa formatos complexos da área de transferência somente quando e se eles forem necessários.
Se uma janela atrasar a renderização de um formato de área de transferência, ela deve 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 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 fazê-lo falhará porque a área de transferência está sendo mantida aberta pelo aplicativo que solicitou o formato a ser 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 da á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 ainda é o proprietário da área de transferência com a função deGetClipboardOwnere, em seguida, colocar identificadores de memória válidos na área de transferência para todos os formatos da área de transferência que ela 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 quaisquer identificadores de memória global na área de transferência.
Todos os formatos da área de transferência que não são renderizados em resposta à mensagem WM_RENDERALLFORMATS 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 atrasada
A renderização atrasada é um recurso de desempenho, permitindo que um aplicativo evite fazer trabalho para renderizar dados da área de transferência em um formato que pode nunca ser solicitado. No entanto, o uso da renderização atrasada envolve as seguintes compensações que devem ser levadas em consideração:
- O uso da renderização atrasada adiciona alguma complexidade ao aplicativo, exigindo que ele manipule duas mensagens de janela de renderização, conforme descrito acima.
- Usar 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 que seja percetível para o usuário. Com a renderização atrasada, se os dados forem eventualmente necessários, a janela deve renderizar os dados enquanto processa uma mensagem de janela de renderização, conforme descrito acima. Como resultado, se os dados forem muito demorados para renderizar, o aplicativo pode ficar visivelmente sem resposta (travado) enquanto a renderização ocorre, 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 renderização atrasada pode, em vez disso, optar por renderizar dados em um thread em segundo plano para manter a resposta da interface do usuário enquanto a renderização ocorre, talvez fornecendo opções de progresso ou cancelamento, que não estão disponíveis ao usar a renderização atrasada.
- Usando renderização atrasada, adicione 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 deSetClipboardDatacom um identificador de NULL e, se os dados forem necessários posteriormente, a janela deve responder a uma mensagem de janela e chamar a função de SetClipboardData uma segunda vez com um identificador para os dados renderizados, conforme descrito acima. Como resultado, se os dados forem eventualmente necessários, o uso da renderização atrasada adiciona o custo de processar uma mensagem de janela e chamar a função SetClipboardData uma segunda vez. Este custo é pequeno, mas não zero. Se um aplicativo suporta apenas um único formato de área de transferência, e se os dados são sempre eventualmente solicitados, o uso de renderização atrasada apenas adiciona essa pequena quantidade de sobrecarga (o custo varia de acordo com o hardware; uma estimativa é entre 10 e 100 microssegundos). No entanto, se os dados forem pequenos, a sobrecarga de usar a renderização atrasada pode exceder o custo para renderizar os dados, o que pode anular a finalidade de usar a renderização atrasada para melhorar o desempenho. (No teste, para dados que já estão em sua forma final, a sobrecarga de usar renderização atrasada excedeu consistentemente o custo para copiar os dados para a área de transferência se os dados fossem de 100 KiB ou menos. Esse teste não inclui o custo para renderizar dados, apenas para copiá-los depois que forem renderizados.)
- A renderização atrasada é uma vantagem líquida de desempenho se economizar mais tempo do que adiciona sobrecarga. Para determinar a sobrecarga da renderização atrasada, a medição é melhor, mas 10 a 100 microssegundos é uma estimativa. Para calcular a economia do uso da renderização atrasada para cada formato da á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 da 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 da área de transferência. A renderização atrasada é uma vantagem líquida de desempenho se a economia exceder o custo geral.
- Como uma diretriz concreta, para aplicativos que suportam apenas um único formato de área de transferência, como texto, onde os dados não são significativamente caros para renderizar, considere colocar os dados diretamente na área de transferência se o tamanho dos dados for de 4 KiB ou menos.
A memória e a á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 da á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. |