Compartir a través de


Operaciones del Portapapeles

Una ventana debe usar el Portapapeles al cortar, copiar o pegar datos. Una ventana coloca los datos en el Portapapeles para las operaciones de cortar y copiar y recupera datos del Portapapeles para las operaciones de pegado. En las secciones siguientes se describen estas operaciones y problemas relacionados.

Para colocar o recuperar datos del Portapapeles, una ventana debe abrir primero el Portapapeles mediante la funciónOpenClipboard. Solo una ventana puede abrir el Portapapeles a la vez. Para averiguar qué ventana tiene abierto el Portapapeles, llame a la función GetOpenClipboardWindow. Cuando haya terminado, la ventana debe cerrar el Portapapeles llamando a la función CloseClipboard .

En esta sección se tratan los temas siguientes.

Operaciones de cortar y copiar

Para colocar información en el Portapapeles, una ventana borra primero cualquier contenido anterior del Portapapeles mediante la función EmptyClipboard. Esta función envía el mensaje WM_DESTROYCLIPBOARD al propietario anterior del Portapapeles, libera los recursos asociados a los datos del Portapapeles y asigna la propiedad del Portapapeles a la ventana que tiene abierto el Portapapeles. Para averiguar qué ventana posee el Portapapeles, llame a la funciónGetClipboardOwner.

Después de vaciar el Portapapeles, la ventana coloca los datos en el Portapapeles en tantos formatos de Portapapeles como sea posible, ordenados del formato del Portapapeles más descriptivo al menos descriptivo. Para cada formato, la ventana llama a la función SetClipboardData, especificando el identificador de formato y un identificador de memoria global. El identificador de memoria puede ser NULL, lo que indica que la ventana representa los datos a petición. Para obtener más información, vea Representación diferida.

Operaciones de pegado

Para recuperar la información de pegado del Portapapeles, una ventana determina primero el formato del Portapapeles que se va a recuperar. Normalmente, una ventana enumera los formatos disponibles del Portapapeles mediante la función EnumClipboardFormats y usa el primer formato que reconoce. Este método selecciona el mejor formato disponible según el conjunto de prioridades cuando los datos se colocaron en el Portapapeles.

Como alternativa, una ventana puede usar la funciónGetPriorityClipboardFormat. Esta función identifica el mejor formato de Portapapeles disponible según una prioridad especificada. Una ventana que reconoce solo un formato de Portapapeles puede determinar simplemente si ese formato está disponible mediante la función IsClipboardFormatAvailable.

Después de determinar el formato del Portapapeles que se va a usar, una ventana llama a la funcióngetClipboardData. Esta función devuelve el identificador a un objeto de memoria global que contiene datos en el formato especificado. Una ventana puede bloquear brevemente el objeto de memoria para examinar o copiar los datos. Sin embargo, una ventana no debe liberar el objeto ni dejarlo bloqueado durante un largo período de tiempo.

Propiedad del Portapapeles

El propietario del Portapapeles de es la ventana asociada a la información del Portapapeles. Una ventana se convierte en el propietario del Portapapeles cuando coloca datos en el Portapapeles, en concreto, cuando llama a la función EmptyClipboard. La ventana permanece el propietario del Portapapeles hasta que se cierra u otra ventana vacía el Portapapeles.

Cuando se vacía el Portapapeles, el propietario del Portapapeles recibe un mensaje WM_DESTROYCLIPBOARD. Estos son algunos de los motivos por los que una ventana puede procesar este mensaje:

  • La ventana retrasada representación de uno o varios formatos del Portapapeles. En respuesta al mensaje de WM_DESTROYCLIPBOARD, la ventana podría liberar recursos que había asignado para representar datos a petición. Para obtener más información sobre la representación de datos, vea Representación diferida.
  • La ventana coloca los datos en el Portapapeles en un formato privado del Portapapeles. El sistema no libera los datos de los formatos privados del Portapapeles cuando se vacía el Portapapeles. Por lo tanto, el propietario del Portapapeles debe liberar los datos al recibir el mensaje WM_DESTROYCLIPBOARD. Para obtener más información sobre los formatos del Portapapeles privados, vea Formatos de Portapapeles.
  • La ventana coloca los datos en el Portapapeles con el formato CF_OWNERDISPLAY portapapeles. En respuesta al mensaje de WM_DESTROYCLIPBOARD, la ventana podría liberar recursos que había usado para mostrar información en la ventana del visor del Portapapeles. Para obtener más información sobre este formato alternativo, vea formato de presentación del propietario.

Representación retrasada

Al colocar un formato del Portapapeles en el Portapapeles, una ventana puede retrasar la representación de los datos en ese formato hasta que se necesiten los datos. Para ello, una aplicación puede especificar NULL para el parámetro hData de la función SetClipboardData. Esto resulta útil si la aplicación admite varios formatos del Portapapeles, algunos o todos los cuales consumen mucho tiempo para representarse. Al pasar un identificador de NULL, una ventana representa formatos complejos del Portapapeles solo cuando y si son necesarios.

Si una ventana retrasa la representación de un formato del Portapapeles, debe estar preparado para representar el formato a petición siempre que sea el propietario del Portapapeles. El sistema envía al propietario del Portapapeles un mensaje WM_RENDERFORMAT cuando se recibe una solicitud para un formato específico que no se ha representado. Al recibir este mensaje, la ventana debe llamar a la función SetClipboardData para colocar un identificador de memoria global en el Portapapeles en el formato solicitado.

Una aplicación no debe abrir el Portapapeles antes de llamar a SetClipboardData en respuesta al mensaje de WM_RENDERFORMAT. No es necesario abrir el Portapapeles y se producirá un error en cualquier intento de hacerlo, ya que la aplicación que solicitó que se represente el formato se mantiene abierto actualmente.

Si el propietario del Portapapeles está a punto de destruirse y ha retrasado la representación de algunos o todos los formatos del Portapapeles, recibe el mensaje WM_RENDERALLFORMATS. Al recibir este mensaje, la ventana debe abrir el Portapapeles, comprobar que sigue siendo el propietario del Portapapeles con la función getClipboardOwner y, a continuación, colocar controladores de memoria válidos en el Portapapeles para todos los formatos del Portapapeles que proporciona. Esto garantiza que estos formatos permanezcan disponibles después de que se destruya el propietario del Portapapeles.

A diferencia de WM_RENDERFORMAT, una aplicación que responde a WM_RENDERALLFORMATS debe abrir el Portapapeles antes de llamar a SetClipboardData para colocar los identificadores de memoria globales en el Portapapeles.

Los formatos del Portapapeles que no se representan en respuesta al mensaje de WM_RENDERALLFORMATS dejan de estar disponibles para otras aplicaciones y ya no se enumeran mediante las funciones del Portapapeles.

Guía de representación retrasada

La representación retrasada es una característica de rendimiento, lo que permite a una aplicación evitar el trabajo para representar datos del Portapapeles en un formato que nunca se puede solicitar. Sin embargo, el uso de la representación diferida implica los siguientes inconvenientes que se deben tener en cuenta:

  • El uso de la representación retrasada agrega cierta complejidad a la aplicación, lo que requiere que controle dos mensajes de ventana de representación, como se ha descrito anteriormente.
  • El uso de la representación diferida significa que la aplicación pierde la opción de mantener la capacidad de respuesta de la interfaz de usuario si la representación de los datos tarda suficiente tiempo en que se nota al usuario. Con la representación diferida, si los datos finalmente son necesarios, la ventana debe representar los datos mientras se procesa un mensaje de ventana de representación, como se ha descrito anteriormente. Como resultado, si los datos tardan mucho tiempo en representarse, la aplicación puede dejar de responder (colgar) visiblemente mientras se produce la representación, ya que no se pueden procesar otros mensajes de ventana mientras se procesa el mensaje de la ventana de representación. Una aplicación que no usa la representación diferida podría optar por representar datos en un subproceso en segundo plano para mantener la respuesta de la interfaz de usuario mientras se produce la representación, quizás proporcionando opciones de progreso o cancelación, que no están disponibles al usar la representación diferida.
  • El uso de la representación retrasada agrega una pequeña cantidad de sobrecarga si los datos finalmente son necesarios. Al usar la representación diferida, una ventana llama inicialmente a la función SetClipboardData con un identificador de NULL y, si los datos son necesarios más adelante, la ventana debe responder a un mensaje de ventana y llamar a la función SetClipboardData una segunda vez con un identificador para los datos representados, como se ha descrito anteriormente. Como resultado, si los datos finalmente son necesarios, el uso de la representación retrasada agrega el costo de procesar un mensaje de ventana y llamar a la función setClipboardData de una segunda vez. Este costo es pequeño pero no cero. Si una aplicación solo admite un único formato de Portapapeles y, si los datos siempre se solicitan, el uso de la representación retrasada solo agrega esta pequeña cantidad de sobrecarga (el costo varía según el hardware; una estimación está entre 10 y 100 microsegundos). Sin embargo, si los datos son pequeños, la sobrecarga del uso de la representación retrasada puede superar el costo de representar los datos, lo que podría derrotar el propósito de usar la representación retrasada para mejorar el rendimiento. (En las pruebas, para los datos que ya están en su forma final, la sobrecarga de usar la representación retrasada superó sistemáticamente el costo de copiar los datos en el Portapapeles si los datos eran 100 KiB o menos. Esta prueba no incluye el costo de representar datos, solo para copiarlos una vez que se represente).
  • La representación retrasada es una ventaja de rendimiento neto si ahorra más tiempo de lo que agrega sobrecarga. Para determinar la sobrecarga de la representación retrasada, la medición es mejor, pero de 10 a 100 microsegundos es una estimación. Para calcular el ahorro de uso de la representación retrasada para cada formato del Portapapeles, mida el costo de representar los datos en ese formato y determine con qué frecuencia se solicita ese formato (en función de los mensajes de ventana descritos anteriormente). Multiplique el costo de representar los datos por el porcentaje de tiempo que los datos no se solicitan finalmente (antes de vaciar el Portapapeles o su cambio de contenido) para determinar el ahorro de representación retrasada para cada formato del Portapapeles. La representación retrasada es una ventaja de rendimiento neto si el ahorro supera el costo de sobrecarga.
  • Como norma concreta, para las aplicaciones que solo admiten un solo formato de Portapapeles, como texto, donde los datos no son significativamente costosos de representar, considere la posibilidad de colocar los datos directamente en el Portapapeles si el tamaño de los datos es de 4 KiB o menos.

Memoria y portapapeles

Se debe asignar un objeto de memoria que se va a colocar en el Portapapeles mediante la función GlobalAlloc con la marca GMEM_MOVEABLE.

Después de colocar un objeto de memoria en el Portapapeles, la propiedad de ese identificador de memoria se transfiere al sistema. Cuando se vacía el Portapapeles y el objeto de memoria tiene uno de los siguientes formatos del Portapapeles, el sistema libera el objeto de memoria llamando a la función especificada:

Función para liberar objeto Formato del Portapapeles
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
ninguno
CF_OWNERDISPLAY
Cuando el Portapapeles está vacío de un objeto CF_OWNERDISPLAY, la propia aplicación debe liberar el objeto de memoria.