Posted on 21. September 2021

Отслеживание в Win32 прав собственности на буфер обмена Windows

В Win32 есть понятие владельца буфера обмена. Как это работает?

Предполагаемое правило состоит в том, что владельцем буфера обмена является окно, которое создало данные, которые в данный момент находятся в буфере обмена.

Предполагаемый шаблон использования для помещения данных в буфер обмена:

Вызовите OpenClipboard (hwnd), в котором вы хотите стать новым владельцем буфера обмена. (Для обсуждения скажем, открыватель буфера обмена - это дескриптор окна, переданный в функцию OpenClipboard.)

Вызовите EmptyClipboard (), чтобы стереть предыдущее содержимое.

Вызовите SetClipboardData () один раз для каждого фрагмента данных, который вы хотите поместить в буфер обмена.

Вызовите CloseClipboard (), чтобы указать, что вы закончили установку данных буфера обмена.

Поздравляем, теперь вы являетесь владельцем буфера обмена.

Владелец буфера обмена получает сообщение WM_RENDERFORMAT, когда кто-то запрашивает данные из буфера обмена, которые были установлены как обработанные с задержкой. Он также получает сообщение WM_RENDERALLFORMATS как часть последовательности уничтожения окна, если он все еще является владельцем буфера обмена на момент его уничтожения. Отрисовка с задержкой позволяет отложить создание сложных данных буфера обмена до момента, когда они будут запрошены. И если этого никто никогда не попросит, то вы сэкономите себе много работы.

Дополнительное чтение: Как правильно обращаться с WM_RENDERFORMAT и WM_RENDERALLFORMATS?

Владелец буфера обмена также получает сообщение WM_DESTROYCLIPBOARD, когда содержимое буфера обмена впоследствии очищается. Это сообщает владельцу буфера обмена, что он может освободить любую память, которая использовалась для создания данных с задержкой рендеринга.

Это сообщает владельцу буфера обмена, что он может освободить любую память, которая использовалась для создания данных с задержкой рендеринга.

• Вызовите OpenClipboard (hwnd), передав окно, которое читает буфер обмена.

• Вызовите GetClipboardData (), чтобы получить данные из буфера обмена.

• Вызовите CloseClipboard (), чтобы указать, что вы закончили чтение данных из буфера обмена.

Если все будут следовать правилам, то все получится.

Спойлер: не все соблюдают правила.

Некоторые программы открывают буфер обмена с целью добавления данных в буфер обмена, а не замены их новыми данными. Эти программы вызывают OpenClipboard, за которым сразу следует SetClipboardData без промежуточного EmptyClipboard.

Исторически не существовало принуждения к тому, что вызывающий SetClipboardData является владельцем буфера обмена. Еще во времена 16-разрядной Windows система предполагала, что приложения работают честно и работают по правилам для общего блага. (И для совместимости эти махинации должны продолжать работать, даже если мир стал более опасным местом.)

Этот сценарий «бонусных данных буфера обмена» создает небольшую проблему, поскольку есть только один владелец буфера обмена (которого вы можете опросить, вызвав GetClipboardOwner ()), но теперь есть два окна, которые совместно помещают данные в буфер обмена. Кто владелец?

Право собственности на буфер обмена изменяется следующим образом:

• Когда вызывается EmptyClipboard (), текущее средство открытия буфера обмена становится владельцем буфера обмена.

• Когда владелец буфера обмена уничтожается, владелец буфера обмена сбрасывается до нуля.

Таким образом, владельца буфера обмена можно описать как «окно, которое в последний раз вызывало EmptyClipboard, если оно все еще существует».

Дополнительнo: существует также специальная обработка случая, когда кто-то передает NULL в OpenClipboard, указывая, что «никто» не открывает буфер обмена.

 

 

Источник 

 



Comments are closed