В чем разница между функциями FreeResource и, скажем, DestroyAcceleratorTable

MaxMax задал несколько воспросов, связанных с ресурсами, начиная с «Как освободить ресурс, заблокированный операцией LockResource?» и заканчивая вопросом «В чем разница между функциями FreeResource и DestroyAcceleratorTable, DestroyObject и т.д.? Были бы гораздо проще использовать единственную функцию вместо набора из пяти функций».

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

  • FindResource;
  • LoadResource;
  • Lock­Resource;
  • использование ресурса;
  • UnlockResource;
  • FreeResource.

Вы можете освободить ресурс, вызвав, эм… UnlockResource.

Несмотря на то, что порядок вызова функций остался прежним, механизмы под капотом отличаются довольно сильно. В 16-битной Windows загрузка ресурса приводила к выделению участка памяти, после чего он заполнялся образом с диска. В Win32 ресурсы отображаются на адресное пространство, которое является частью образа — здесь нет выделения памяти и явной загрузки.

Следующая вещь, которую нужно понять, заключается в том, что ресурсы — это просто блоки двоичных данных. Это не настоящие объекты. Нет объекта HBITMAP, который где-то сидит и ждет, пока его не найдут.

Относитесь к данным ресурсов как к набору чертежей. Если вы вызываете FindResource + LoadResource + LockResource, вы получаете чертеж радио, но это не то же самое, что держать в руках настоящее радио. Чтобы достичь этой цели, вам нужно вручить чертеж этого радио кому-то, кто понимает чертежи электрических схем и знает, как спаять провода вместе, чтобы получить из потенциального радио настоящее радио.

Если вы следили за спорадическими сериями статей о форматах ресурсов, вы уже знаете, что эти схематические диаграммы зачастую довольно сложны. Функция LoadBitmap сначала выполняет ритуальный танец FindResource + LoadResource + LockResource, чтобы получить чертеж растрового изображения, но после этого ей нужно сформировать настоящее растровое изображение, что производится при помощи разбора исходных двоичных данных ресурса и попытки разобраться в них посредством функций CreateBitmap и SetDIBits для преобразования чертежа в настоящее растровое изображение.

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

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