Как обрабатывать удаление шрифта в пользовательском элементе управления?

#c# #winforms #fonts #gdi

#c# #winforms #шрифты #gdi

Вопрос:

Удаление шрифтов кажется мне немного странным. Если у меня, например, есть элемент управления label и я использую шрифт, который он использует, как label1.Font.Dispose(); , он все равно отлично отрисовывается.

Если я вместо этого попытаюсь немедленно использовать удаляемый шрифт, это приведет к сбою, например

 var f = new Font("Arial", 14);
f.Dispose();
g.DrawString("Hello", f, Brushes.Black, 20, 20);
  

за исключением Invalid parameter .

Последнее кажется мне более интуитивным, учитывая, что я пытаюсь использовать удаляемый шрифт.
Я не могу понять, почему надпись по-прежнему отображается нормально, потому что в ссылочном источнике надписи я вижу, что шрифт просто используется немедленно без какой-либо проверки: e.Graphics.DrawString(Text, Font, brush, face, stringFormat); .

Суть вопроса в том, что у меня есть пользовательский элемент управления, который — как и другие элементы управления — использует шрифты в качестве свойств и реализует IDisposable . Теперь мне интересно, должен ли я удалить свойства шрифта, потому что я не могу знать, например, было ли установлено свойство font на шрифт, который все еще необходим.

Control кажется, использует какой-то FontHandleWrapper класс внутри, который я не совсем понимаю, если честно. Но даже если я удаляю шрифт в своем пользовательском элементе управления (который у меня есть во внешней библиотеке) извне, он все равно отлично отображается, и я сразу использую шрифты там.

Кто-нибудь может объяснить, почему я могу удалять один шрифт, а не другой? Должен ли я оставить шрифты в покое в методе Dispose моего пользовательского элемента управления или утилизировать их?

Комментарии:

1. Шрифт, используемый непосредственно, — это шрифт, назначенный Font свойству элемента управления. Старый шрифт удаляется при изменении шрифта: Control. OnFontChanged . Если вы создаете одноразовый объект, затем удалите его на месте, когда закончите с ним. Если объект Font является чем-то, что должно сохраняться, удалите его с помощью Dispose(bool disposing) метода.

2. FontHandleWrapper Обрабатывает текущий дескриптор шрифта и создает / удаляет дескриптор ( DeleteObject(new HandleRef(this, handle)) => [gdi32].IntDeleteObject(HandleRef hObject) ) при необходимости. Существует также функция шрифта по умолчанию, функция резервного копирования шрифта (…)

3. Хорошо, это все еще довольно сложно, когда дело доходит до деталей, например, я инициализирую свойства новым шрифтом (—> я должен их удалить), но они также могут быть установлены извне (—> я не должен их удалять). Я изучу это подробнее. Я столкнулся с проблемами, когда функция создала множество таких элементов управления, и, не удалив шрифты, я предполагаю, что у меня закончились дескрипторы или что-то в этом роде.

4. На самом деле вам не нужно удалять шрифт, если вы задаете ему свойство Font. Это обрабатывается внутри. Проведите тест, повторно установив для свойства Font элемента управления значение random new Font() с помощью инструмента диагностики и открытого представления ресурсов приложения в TaskManager. Вы увидите, что на самом деле вы не пропускаете дескрипторы и / или объекты. Вы заметите небольшое увеличение использования памяти. Затем выполните тестовое удаление шрифта. Проведите сравнение.