Обнаружение создания легко. Просто переопределите CreateHandle
в потомке TControlCanvas
и поместите вместо него значение по умолчанию , поскольку ответ Джероена демонстрирует . Обнаружение разрушения сложнее.
Один из способов избежать этой проблемы состоит в том, чтобы проверить, совпадает ли дескриптор TGpGraphics с дескриптором блока рисования, поэтому вместо того, чтобы определять момент, когда контекст устройства освобожден, вы просто проверяете его перед тем, как узнаете. *
if not Assigned(FGraphics)
or (FGraphics.GetHDC <> PaintBox1.Canvas.Handle) then begin
FGraphics.Free;
FGraphics := TGpGraphics.Create(PaintBox1.Canvas.Handle);
end;
Это, вероятно, не надежно; значения дескриптора могут быть использованы повторно, поэтому, хотя значение HDC может быть одинаковым между двумя проверками, нет гарантии, что оно по-прежнему ссылается на один и тот же объект контекста устройства ОС.
Базовый класс TCanvas
никогда не очищает свое собственное свойство Handle
, поэтому все, что делает недействительным холст, должно происходить извне. TControlCanvas
очищает свое свойство Handle
, когда его свойство Control
получает новое назначение, но обычно это происходит только при создании элемента управления, поскольку экземпляры TControlCanvas
редко используются совместно. Однако TControlCanvas
экземпляры работают из пула дескрипторов контекста устройства, которые хранятся в CanvasList
. Когда одному из них требуется DC (в TControlCanvas.CreateHandle
), он вызывает FreeDeviceContext
, чтобы освободить место в кэше холста для дескриптора, который он собирается создать. Эта функция вызывает (не виртуальный) метод FreeHandle
. Размер кэша равен 4 (см. CanvasListCacheSize
), поэтому, если в вашей программе есть несколько потомков TCustomControl
или TGraphicControl
, высока вероятность того, что вы получите ошибки кеширования, когда потребуется перекрасить более четырех из них сразу.
TControlCanvas.FreeHandle
не является виртуальным и не вызывает никаких виртуальных методов. Хотя вы можете сделать потомком этого класса и предоставить ему виртуальные методы, остальная часть VCL будет продолжать вызывать не виртуальные методы, не обращая внимания ни на одно из ваших дополнений.
Вместо того, чтобы пытаться определить, когда был выпущен контекст устройства, вам лучше использовать другой конструктор TGpGraphics. Используйте тот, который принимает дескриптор окна вместо дескриптора DC, например. Разрушение оконной ручки намного легче обнаружить. Для одноразового решения назначьте свой собственный метод свойству TPaintBox.WindowProc
и следите за сообщениями wm_Destroy
. Если вы делаете это часто, то создайте класс-потомок и переопределите DestroyWnd
.