ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы.



 

Часть 20

Глава 18. Более подробно о ресурсах
Программы Windows очень легко использовать, т.к. они предоставляют пользователю стандартный интерфейс. Например, большинство программ Windows используют меню для реализации команд программы, и курсор, который позволяет использовать мышь в качестве управл
ения такими инструментами, как указывающая стрелка или кисть для рисования.
Меню и курсоры это два примера ресурсов программы Windows. Ресурсы это данные, хранимые в исполняемом (.EXE) файле программы, но они располагаются отдельно от обычного сегмента данных программы. Ресурсы разрабатываются и специфицируются вне кода программ
ы, затем добавляются к откомпилированному коду программы для создания исполняемого файла программы.
Эти ресурсы вы будете создавать и использовать наиболее часто:
- Меню
- Блоки диалога
- Пиктограммы
- Курсоры
- Клавишные акселераторы
- Побитовые распределения
- Строки символов
Обычно при загрузке приложения в память Windows оставляет ресурсы на диске и загружает в случае необходимости отдельные ресурсы в процессе выполнения программы. За исключением побитовых распределений, Windows удаляет ресурс из памяти после окончания его 
использования. Если вы хотите загрузить ресурс при загрузке программы или не хотите, чтобы Windows имел возможность удалить ресурс из памяти, вы можете сменить его атрибуты. Детальное описание создания и модификации ресурсов содержится в "Набор описание 
создания и модификации ресурсов содержится в "Набор инструментальных средств Whitewater для работы с ресурсами".
Создание ресурсов
Вы можете создавать ресурсы используя редактор ресурсов или компилятор ресурсов. Turbo Pascal для Windows поддерживает оба эти метода, поэтому вы сами можете выбрать, какой их них является более удобным. В большинстве случаев проще использовать редактор 
ресурсов и создавать ваши ресурсы визуально. Однако, иногда более удобно использовать компилятор ресурсов для компиляции файла описания ресурса, который может вам встретиться в книге или в журнале.
Независимо от выбранного вами подхода вы обычно создаете файл ресурса (.RES) для каждого приложения. Этот файл ресурса будет содержать двоичную информацию о всех меню, диалогах, побитовых распределениях и других ресурсах, используемых вашим приложением. 

Двоичный файл ресурса (.RES) добавляется к вашему исполняемому файлу (.EXE) в процессе компиляции с использованием директивы компилятора $R, как это описано в данной главе. Вы также должны написать код, который будет загружать ресурсы в память. Это прида
ст вам дополнительную гибкость, поскольку ваша программа будет использовать память лишь для ресурсов, которые используются в данный момент. Загрузка ресурсов в память также рассматривается в данной главе.
Добавление ресурсов к исполняемой программе
Ресурсы хранятся в двоичном формате в файле .RES, поэтому они должны быть добавлены к исполняемому файлу приложения (.EXE). Результатом будет файл, который наряду с откомпилированным кодом приложения будет содержать и его ресурсы.
Есть три способа добавления ресурсов к исполняемому файлу:
- Использовать редактор ресурсов для копирования ресурсов из файла   .RES в уже скомпилированный файл программы .EXE. Инструкции по   этой операции содержатся в руководстве "Набор инструментальных   средств Whitewater для работы с ресурсами".
- Задать директиву в исходном коде файла. Например, эта программа   на языке Pascal:
  program SampleProgram;
  {$r SAMPLE.RES}
  ...
  добавит файл ресурсов SAMPLE.RES к исполняемому файлу. Каждая   программа на языке Pascal может иметь только один файл ресурсов   (хотя этот файл ресурсов может включать другие файлы ресурсов).   Все эти файлы должны быть файлами .RES и хранить ресурсы
 в   двоичном формате. Директива компилятора $R позволяет вам задать   отдельный файл .RES.
- Использовать компилятор ресурсов, рассматриваемый в данной   главе.
Работа с Компилятором Ресурсов
Использование редактора ресурсов подробно рассмотрено в руководстве "Набор инструментальных средств Whitewater для работы с ресурсами". Данный раздел содержит краткое описание Компилятора Ресурсов фирмы Microsoft для создания файлов ресурсов.
Компилятор Ресурсов это приложение DOS, которое берет на входе файл описания ресурсов и генерирует двоичный файл ресурсов. Кроме того, Компилятор Ресурсов добавляет ресурсы непосредственно в исполняемый файл, избавляя вас от необходимости использования д
ирективы Turbo Pascal $R для добавления ресурсов в программу. Это очень удобно, если нужно сменить ресурсы исполняемой программы, а у вас нет доступа к исходному коду на языке Pascal.
Компилятор Ресурсов можно запустить в ответ на подсказку DOS или в окне DOS в Windows. Формат следующий:
RC [опции] <входной файл .RC> [выходной файл .EXE]
где элементы в прямоугольных скобках являются необязательными.
Например:
RC -r SAMPPROG.RC
Из входного файла описания SAMPPROG.RC по данной команде будет создан файл SAMPPROG.RES. Затем файл SAMPPROG.RES должен быть присоединен к исполняемому файлу SAMPPROG.EXE с помощью директивы компилятора Turbo Pascal $R или запуска компилятора ресурсов с 
файлом .RES:
RC SAMPPROG.RES
Это присоединит существующий двоичный файл ресурсов к файлу SAMPPROG.EXE и избавит вас от необходимости использования компилятора Turbo Pascal.
В качестве альтернативы вы можете скомбинировать оба эти шага в непосредственную модификацию существующего файла .EXE путем добавления в него ресурсов. В этом случае нужно использовать команду:
RC SAMPPROG.RC
По этой команде из входного файла описания SAMPPROG.RC будет создан файл SAMPPROG.RES, который будет непосредственно добавлен к файлу SAMPPROG.EXE и заменит любые существующие ресурсы.
В любом случае программа SAMPPROG.PAS на языке Pascal должна содержать команды по загрузке ресурсов в память.
Имеются следующие опции командной строки Компилятора Ресурсов:
     Таблица 18.1. Опции командной строки Компилятора Ресурсов
----------------------------------------------------------------
Опция     Значение
----------------------------------------------------------------
-r        Создание файла .RES
-l        Создание приложения, которое использует LIM 3.2 EMS
-e        Создание драйвера, который использует память EMS
-m        Установить флаг множества экземпляров
-p        Создать частную библиотеку
-t        Создать защищенный режим приложения
-v        Вербация (печать сообщений о процессе)
-d        Определить символ
-fo       Переименовать файл .RES
-fe       Переименовать файл .EXE
-i        Добавить траекторию для поиска INCLUDE
-x        Игнорировать переменную среды INCLUDE
-k        Хранить сегменты в соответствии с файлом .DEF (не
          сортировать сегменты для быстрой загрузки)
----------------------------------------------------------------
Файлы описания Компилятора Ресурсов
Входной файл описания .RC представляет собой описание ресурса в текстовом виде, которое компилируется в двоичный формат. Задание ресурсов в формате Компилятора Ресурсов больше похоже на написание программы. Вместо рассмотрения сложных определений языка о
писаний Компилятора Ресурсов, вам будут показаны несколько примеров. В них будет все, что нужно знать для компиляции и редактирования файлов описаний. Помните о том, что в большинстве случаев проще использовать редактор ресурсов для создания сложных ресу
рсов. Вы также можете генерировать файлы описаний ресурсов непосредственно из редактора ресурсов, если в этом есть необходимость.
В приведенном ниже примере показан типичный файл описания ресурсов SAMPPROG.RC:
; SAMPPROG.RC -- a sample resource script file
;             -- this script illustrates the use of icons,
;                strings, menus and dialog resources in Windows
;             -- this script would be compiled with the resource
;                compiler and then appended to the pascal program
;                using the $R compiler directive
; include C-style header files for constant definition:
#include 
#include 
#include 
; define icons in saparate files
SampleIcon     ICON      sample.ico
; strings can be defined numerically or symbolically
STRINGTABLE
BEGIN
 ids_NoProgrm, "Program unavailable"
 ids_Invalid, "Invalid, "Invalid entry"
 ids_Fatal, "Fatal error !"
; .
; . other strings go here
; .
END
; Menus define commands for the user
SampleMenu MENU
BEGIN
 POPUP "&File"
  BEGIN
   MENUITEM "&New..\tCtrl+N",           cm_FileNew
   MENUITEM "&Open..\tCtrl+O",          cm_FileOpen
   MENUITEM "&Save..\tCtrl+S",          cm_FileSave
   MENUITEM SEPARATOR
   MENUITEM "&Print\tCtrl+P",           cm_FilePrint
  END
 POPUP "&Edit"
  BEGIN
   MENUITEM "&Undo\tAlt+BkSp",          cm_EditUndo
   MENUITEM SEPARATOR
   MENUITEM "&Cut\tShift+Del",          cm_EditCut
   MENUITEM "C&opy\tIns",               cm_EditCopy
   MENUITEM "&Paste\tShift+Ins",        cm_EditPaste
   MENUITEM "&Delete\tDel",             cm_EditDelete
   MENUITEM "C&lear All\tCtrl+Del",     cm_EditClear
  END
 POPUP "&View"
  BEGIN
   MENUITEM "Summary\tF2",              cm_ViewSummary
   MENUITEM "Graph\tF3",                cm_ViewGraph
  END
 END
; Accelerators provide "hot keys" to menus, commsnds
SampleAccelerators ACCELERATORS
BEGIN
 "^n", cm_FileNew
 "^o", cm_FileOpen
 "^s", cm_FileSave
 "^p", cm_FilePrint
 VK_DELETE, cm_EditCut, VIRTKEY, SHIFT
 VK_INSERT, cm_EditCopy, VIRTKEY
 VK_INSERT, cm_EditPaste, VIRTKEY, SHIFT
 VK_DELETE, cm_EditDelete, VIRTKEY
 VK_DELETE, cm_EditClear, VIRTKEY, CONTROL
 VK_BACK, cm_EditUndo, VIRTKEY, ALT
 VK_F2, cm_ViewSummary, VIRTKEY
 VK_F3, cm_ViewGraph, VIRTKEY
END
; Dialog boxes display information to the user
AboutBox DIALOG 20, 20, 160, 80
CAPTION "About SAMPPROG"
STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
FONT 8, "Helv"
BEGIN
 CTEXT "Sample Program"            -1,  0,   10,  160, 10
 CTEXT "Written in Turbo Pascal"   -1,  0,   26,  160, 10
 CTEXT "for Windows 3.0"           -1,  0,   36,  160, 10
 ICON "Sample_Icon"                -1,  8,    8,    0,  0
 DEFPUSHBUTTON "OK",             IDOK, 60,   56,   40, 14
END
FileOpen DIALOG 20, 20, 204, 124
CAPTION "File Open"
STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
FONT 8, "Helv"
BEGIN
 LTEXT    "File&name:", -1,  6,   8,  36,  10
 EDITTEXT              100, 42,   6,  98,  12 ES_AUTOHSCROLL
 LTEXT    "Directory:", -1,  6,  20,  36,  10
 LTEXT    ""           101, 42,  20,  98,  10
 LTEXT    "&Files:",    -1,  6,  32,  64,  10
 LISTBOX 102, 6, 44, 64, 82, WS_TABSTOP | WS_VSCROLL | LBS_SORT
 LTEXT    "Directories:", -1,  76,  32,  64,  10
 LISTBOX 103, 76, 44, 64, 82, WS_TABSTOP | WS_VSCROLL | LBS_SORT
 DEFPUSHBUTTON "OK",      IDOK, 146,   6,   50, 14
 PUSHBUTTON "Cancel", IDCANCEL, 146,  24,   50, 14
END
Файл заголовков SAMPPROG.H состоит из определений констант в стиле языка С. Ниже показан типичный файл заголовков:
/* SAMPPROG.H -- header file of constants for SAMPPROG.RC */
#define ids_NoProgrm          601
#define ids_Invalid           602
#define ids_Fatal             603
#define ids_FileNew           701
#define ids_FileSave          702
/*
 .
 . other constants included here
 .
*/
Замечания о Компиляторе Ресурсов
Следует сделать несколько замечаний о языке программирования описаний Компилятора Ресурсов:
1. Комментарии начинаются с точки с запятой (;) и продолжаются до    конца строки. Вы можете использовать комментарии в стиле языка    С, которые представляют собой текст, заключенный между /* и */.
2. Компилятор Ресурсов не делает отличий для прописных и строчных    букв в ключевых словах, подобных BEGIN и END.
3. Компилятор Ресурсов различает прописные и строчные буквы в    символьных именах, подобных cmFileNew и AboutBox.
4. В качестве разделителя в Компиляторе Ресурсов можно    использовать произвольное число пробелов.
5. Для включения файла заголовков констант вы должны использовать    директиву #include. Это определяется использованием команды    #define в стиле языка С.
6. Вы можете использовать директиву #rcinclude для включения    других файлов описаний ресурсов (*.RC или *.DLG); например, для    включения откомпилированных блоков диалога.
7. Лучше всего использовать имена символьных констант, чем числа,    для ID строк, ID команд меню и т.п. Они обычно определяются в    файле заголовков, используя определение константы в стиле языка    С. Вам придется определить константы языка Pascal в в
ашей    программе для ссылки на эти символьные константы.
8. Каждый ID константы команды элемента меню и ID строки должен    быть уникальным.
9. Меню могут быть произвольно вложены друг в друга, создавая тем    самым иерархию меню.
10. Амперсанд (&) внутри элемента управления меню или диалога     показывает, что программа подчеркнет следующий символ. Можно     получить доступ к подчеркнутому управлению меню или диалога,     нажав клавишу Alt и подчеркнутый символ.
11. Текст \t внутри элемента меню генерирует символ табуляции для     выделения текста. Это часто используется для выделения     эквивалентов команд клавиатуры.
12. Активные клавиши должны быть определены в таблице     акселераторов. Включенный в меню текст не создает     автоматически акселераторы.
13. Управления подобные статичному тексту, к которым программа не     организует доступ, имеют ID -1.
14. Местоположение диалога и управления задается в следующей     последовательности: левая граница, верхняя граница, ширина,     высота.
15. Элементы меню, диалоги и элементы управления диалогом подобные     линейкам прокрутки, полям редактирования и кнопкам, могут быть     модифицированы константами стиля Windows. Они добавляются с     помощью побитового оператора or, который представляе
т собой     вертикальную черту (|). Например, элементы управления могут     иметь стиль WS_CHILD, WS_TABSTOP и WS_BORDER.
16. Файлы описания ресурсов должны компилироваться с     использованием Компилятора Ресурсов.
17. В большинстве случаев проще использовать редактор ресурсов,     чем писать сложные определения ресурсов в файлах описаний.
18. Для загрузки и использования ресурсов вы должны включить     соответствующий код в вашу программу на языке Turbo Pascal.
Загрузка ресурсов в приложение
После добавления ресурса к исполняемому файлу, он должен быть явно загружен приложением до своего использования. Конкретный способ загрузки ресурса зависит от типа ресурса.
Загрузка меню
Меню окна является одним из атрибутов его создания. Другими словами это характеристика окна, которая должна быть задана до создания соответствующего элемента меню (с помощью метода Create). Следовательно, меню может быть задано в типе конструктора Init и
ли вскоре после конструирования. Ресурсы меню загружаются вызовом функции Windows LoadMenu со строкой ID меню при конструировании нового объекта окна. Например:
constructor SampleMainWindow.Init(AParent: PWindowsObject;
 ATitle: PChar);
begin
 TWindow.Init(AParent, ATitle);
 Attr.Menu:=LoadMenu(HInstance, PChar(100));
 ...
end;
Код PChar(100) переводит целое значение 100 в тип PChar, совместимый с Windows тип строки.
LoadMenu загружает ресурс меню с ID 100 в новый объект окна. Ресурс может иметь символьное имя (строку), например, 'SampleMenu', а не числовой идентификатор. В этом случае предыдущий код будет выглядеть следующим образом:
constructor SampleMainWindow.Init(AParent: PWindowsObject;
 ATitle: PChar);
begin
 TWindow.Init(AParent, ATitle);
 Attr.Menu:=LoadMenu(HInstance, 'SampleMenu');
 ...
end;
Дополнительная информация по созданию объектов окна содержится в Главе 10, "Объекты окна".
Для обработки выбора варианта меню просто определяется метод для окна, которое владеет этим меню, используя специальное расширение заголовка определения метода идентификатором cm_First:
procedure HandleMenu101(var Msg: TMessage); virtual cm_First+101;
Обратите внимание на то, что 101 есть ID выбранного варианта меню (а не самого ресурса меню). Каждый вариант меню имеет уникальный целый ID. В этом методе задача состоит в организации соответствующей реакции на выбор варианта меню. Обычно вы будете опред
елять символьные константы для команд вашего меню.
Загрузка таблиц акселераторов
Акселераторы это активные клавиши или комбинации клавиш, которые используются для задания команд приложения. Обычно акселераторы определяются как эквиваленты выбора вариантов меню. Например, клавиша delete это стандартный акселератор, который можно испол
ьзовать как альтернативу выбора варианта Delete в меню Edit. Однако, акселераторы могут реализовывать команды, которые не соответствуют элементам меню.
Ресурсы акселератора хранятся в таблице акселераторов. Для загрузки таблицы акселераторов используется функция Windows LoadAccelerators, которая просто возвращает регулятор таблицы. В отличие от ресурса меню, который связан с конкретным окном, ресурс акс
елератора принадлежит всему приложению. Каждое приложение может иметь только один такой ресурс. Объекты приложения резервируют одно поле объекта, HAccTable, для хранения регулятора ресурса акселераторов. Обычно вы будете загружать ресурс акселераторов в 
методе объекта приложения InitInstance:
procedure SampleApplication.InitInstance;
begin
 TApplication.InitInstance;
 HAccTable:=LoadAccelerators(HInstance, 'SampleAccelerators');
end;
Часто вы будете определять акселераторы для быстрого выбора вариантов меню. Например, Shift-Ins обычно используется для быстрого выбора Paste. Акселераторы генерируют основанные на команде сообщения, которые идентичны сообщениям, генерируемым выбором вар
ианта меню. Для привязки метода реакции на выбор варианта меню с соответствующей клавишей акселератора нужно убедиться в том, что определенное в ресурсе значение акселератора идентично ID элемента меню.
Загрузка блоков диалога
Блоки диалога являются единственным типом ресурса, который непосредственно соответствует типу объекта ObjectWindows. TDialog и его производные типы, включая TDlgWindow, определяют объекты интерфейса, которые используют ресурсы блока диалога. Каждый объек
т блока диалога обычно связан с одним ресурсом блока диалога, который задает его размер, местоположение и ассортимент управлений (таких, как кнопки и блоки списка).
Задайте ресурс объекта блока диалога при конструировании блока диалога. Как ресурсы меню и акселераторов, ресурс диалога может иметь символьное имя или целый ID. Например:
Adlg:=New(PSampleDialog, Init(@Self, 'AboutBox'));
или
Adlg:=New(PSampleDialog, Init(@Self, PChar(120)));
Дополнительная информация по созданию объектов диалога содержится в Главе 5, "Организация диалога".
Загрузка курсоров и пиктограмм
Каждый тип объекта окна имеет специальные атрибуты, называемые атрибутами регистрации. Среди этих атрибутов есть курсор окна и пиктограмма. Для установления этих атрибутов для типа окна вы должны определить метод GetWindowClass (как и GetClassName).
Например, вы создаете курсор для выбора элементов в блоке списка. Курсор имеет вид указательного пальца и хранится в ресурсе курсора с именем 'Finger'. Кроме того, вы создаете ресурс пиктограммы с именем 'SampleIcon', который выглядит как улыбающееся лиц
о. Вы должны написать метод GetWindowClass следующим образом:
procedure SampleWindow.GetWindowClass(var AWndClass: TWndClass);
begin
 TWindow.GetWindowClass(AWndClass);
 AWndClass.hCursor:=LoadCursor(HInstance, 'Finger');
 AWndClass.hIcon:=LoadIcon(HInstance, 'SampleIcon');
end;
Однако, между курсором и пиктограммой имеется одно отличие. Оно состоит в том, что курсор задается для одного окна, а пиктограмма представляет все приложение. Следовательно, пиктограмма устанавливается в типе объекта только для головного окна. У этого пр
авила имеется одно исключение: для приложений, которые следуют правилам интерфейса множественного документа (MDI), каждое дочернее окно MDI имеет свою собственную пиктограмму.
Для использования одного из уже имеющихся курсоров или пиктограмм Windows, передайте 0 в HInstance и используйте значение idc_ (например, idc_IBeam) для курсора и значение idi_ (например, idi_Hand) для пиктограммы. Например:
procedure SampleWindow.GetWindowClass(var AWndClass: TWndClass);
begin
 TWindow.GetWindowClass(AWndClass);
 AWndClass.hCursor:=LoadCursor(HInstance, idc_IBeam);
 AWndClass.hIcon:=LoadIcon(HInstance, idi_Hand);
end;
Дополнительную информацию по регистрационным атрибутам окна можно найти в Главе 10, "Объекты окна".
Загрузка ресурсов строк
Принципиальная причина выделения строк приложения в качестве ресурсов состоит в облегчении процесса настройки приложения на конкретное применение или возможности перевода приложения на иностранный язык. Если строки определены в исходном коде, то для их и
зменения или перевода нужно иметь доступ к исходному коду. Если же они определены как ресурсы, то они хранятся в таблице строк исполняемого файла приложения. Вы можете использовать редактор строк для перевода строк в таблице, без изменения и даже доступа
 к исходному коду. Каждый исполняемый файл может иметь только одну таблицу строк.
Для загрузки строки из таблицы в буфер сегмента данных вашего приложения используется функция LoadString. Синтаксис LoadString следующий:
LoadString(HInstance, StringID, @TextItem, SizeOf(TextItem));
- Параметр StringID это номер ID строки (например, 601) в таблице   строк. Это число можно заменить константой.
- Параметр @TextItem это указатель на массив символов (PChar),   который принимает строку.
- Параметр SizeOf(TextItem) это максимальное число символов,   передаваемых в @TextItem. Максимальный размер ресурса строки 255   символов, поэтому передача буфера из 256 символов гарантирует   полную передачу строки.
LoadString возвращает число скопированных в буфер символов, или ноль если ресурс не существует.
Вы можете использовать ресурс строки для вывода текста в блоке сообщения. Например, вы можете вывести сообщение об ошибке. В данном примере вы определяете строку 'Program unavailable' в таблице строк и определяете константу ids_NoProgrm в качестве ID стр
оки. Для использования этого ресурса строки в блоке сообщения об ошибке, вы можете написать следующую процедуру:
procedure TestDialog.RunErrorBox(ErrorNumber: Integer); virtual;
var
 TextItem: array[0..255] of Char;
begin
 LoadString(HInstance, ids_NoPrgrm, @TextItem, 20);
 MessageBox(HWindow, @TextItem, 'Error', mb_OK or
  mb_IconExclamation);
end;
Данный пример загружает отдельную строку в блок сообщения об ошибке. Для загрузки списка строк в блок списка вызывается LoadString для загрузки каждой строки, затем вызывается AddString для добавления ее в блок списка.
Другое использование ресурса строк применяется для элементов меню, которые добавляются в меню вашего исходного кода. В этом случае сначала получается ресурс строки с помощью LoadString. Затем эта строка передается как параметр в вызовы функций Windows Cr
eateMenu и AppendMenu. Например:
procedure SampleWindow.Init(AParent: PWindpwsObject; ATitle:
 PChar);
var
 TextItem: array[0..255] of Char;
begin
 TWindow.Init(AParent, ATitle);
 Attr.Menu:=LoadMenu(HInstance, PChar(100));
 LoadString(HInstance, 301, @TextItem, 20);
 AppendMenu(Attr.Menu, mf_String ormf_Enabled, 501, @TextItem);
end;
Загрузка побитовых распределений
Функция Windows LoadBitmap загружает ресурсы побитовых распределений. LoadBitmap загружает побитовое распределение в память и возвращает его регулятор. Например:
HMyBit:=LoadBitmap(HInstance, PChar(501));
загружает ресурс побитового распределения с идентификатором 501 и записывает его регулятор в переменную HMyBit. После загрузки побитового распределения оно останется в памяти до его явного удаления вами. В отличие от других ресурсов, оно остается в памят
и даже после закрытия пользователем вашего приложения.
В Windows имеется ряд заранее определенных побитовых распределений, которые используются как часть графического интерфейса Windows. Ваше приложение может загружать эти распределения (например, obm_DnArrow, obm_Close и obm_Zoom. Как заранее определенные п
иктограммы и курсоры, заранее определенные побитовые распределения могут быть загружены, если в вызове LoadBitmap вместо HInstance задать ноль:
HMyBit:=LoadBitmap(0, PChar(obm_Close));
После загрузки побитового распределения ваше приложение может использовать его разными способами:
- Для рисования картинки на экране. Например, вы можете загрузить   побитовое распределение в блок информации о приложении в качестве   заставки.
- Для создания кисти, которую вы можете использовать для   заполнения областей экрана или для создания фона окна. Создав   кисть по побитовому распределению, вы можете закрасить ей   область фона. 
- Для отображения картинок вместо текста в элементах меню или   элементах блока списка. Например, вы можете вместо слова 'Arror'   (стрела) в варианте меню поместить изображение стрелки.
Дополнительная информация относительно использования побитовой графики содержится в Главе 17, "Все о GDI".
Если побитовое распределение не используется, то его нужно удалить из памяти. В противном случае занимаемая им память будет недоступна другим приложениям. Даже если вы не удаляете его после использования приложением, вы обязательно должны удалить его до 
прекращения работы приложения.
Побитовое распределение удаляется из памяти с помощью функции Windows DeleteObject:
if DeleteObject(HMyBit) then {успешно};
После удаления побитового распределения его регулятор становится некорректным и его нельзя использовать.
Использование побитовых распределений для создания кистей
Вы можете использовать побитовые распределения для создания кистей, которые могут закрашивать области экрана. Область может быть закрашена сплошным цветом или в виде заданного образца.
Минимальный размер используемого в кисти побитового распределения составляет 8 на 8 пикселей. Если вы используете большее побитовое распределение, то в кисти используется только его левый верхний угол 8 на 8. 
Предположим, что вы хотите заполнить область полосками, как это показано на Рис.18.1. Для этого вы можете использовать редактор ресурсов для создания образца из двух полос, показанных на Рис.18.2, размером 8 на 8 пикселей. Затем, в вашем исходном коде вы
 можете загрузить это побитовое распределение и создать по нему кисть. При заполнении области на Рис.18.1 Windows циклически копирует кисть.
Рис.18.1. Заполнение области экрана полосками
Действительный размер побитового распределения лишь 8 на 8 пикселей, но кистью можно закрасить весь экран.
Рис.18.2. Ресурс побитового распределения для создания кисти                по образцу Рис.18.1
Следующий код помещает образец побитового распределения в кисть:
procedure SampleWindow.MakeBrush;
var
 MyLogBrush: TLogBrush;
begin
 HMyBit:=LoadBitmap(HInstance, PChar(502));
 MyLogBrush.lbStyle:=bs_Pattern;
 MyLogBrush.lbHatch:=HMyBit;
 TheBrush:=CreateBrushInderect(@MyLogBrush);
end;
Для проверки образца, отобразим его в прямоугольнике:
procedure MyWindow.Paint(PaintDC: HDC; var PaintInfo: TPaintStruct);
begin
 SelectObject(PaintDC, TheBrush);
 Rectangle(PaintDC, 20, 20, 200, 200);
end;
После использования кисти вы должны удалить и кисть и побитовое распределение:
DeleteObject(HMyBit);
DeleteObject(TheBrush);
Отображение побитовых распределений в меню
Для отображение побитовых распределений в меню используется функция ModifyMenu. Она меняет существующий элемент меню таким образом, что выводит побитовое отображение вместо текста варианта меню, определенного в редакторе меню. Например, этот конструктор 
Init добавляет и модифицирует меню окна:
type
 MyLong=record
  case Integer of
   0: (TheLong: Longint);
   1: (Lo: Word;
       Hi: Word);
 end;
constructor SampleWindow.Init(AParent: PWindowsObject; ATitle:
 PChar);
var
 ALong: MyLong;
begin
 TWindow.Init(AParent, ATitle);
 Attr.Menu:=LoadMenu(HInstance, PChar(100));
 ALong.Lo:=LoadBitmap(HInstance, PChar(503));
 ModifyMenu(Attr.Menu, 111, mf_ByCommand or mf_Bitmap, 211,
  PChar(ALong.TheLong));
 ...
end;
В приведенном выше коде 111 это ID команды варианта меню, который изменяется, а 211 это его новый ID. Однако, вы можете использовать один и тот же ID в обоих случаях.
Рис.18.3. Меню, где в качестве одного из вариантов выбора использовано побитовое распределение



Яндекс цитирования